| File: Binder\BindingDiagnosticBag.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; using System.Collections.Immutable; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis.CSharp { internal sealed class BindingDiagnosticBag : BindingDiagnosticBag<AssemblySymbol> { private static readonly ObjectPool<BindingDiagnosticBag> s_poolWithBoth = new ObjectPool<BindingDiagnosticBag>(() => new BindingDiagnosticBag(s_poolWithBoth!, new DiagnosticBag(), new HashSet<AssemblySymbol>())); private static readonly ObjectPool<BindingDiagnosticBag> s_poolWithDiagnosticsOnly = new ObjectPool<BindingDiagnosticBag>(() => new BindingDiagnosticBag(s_poolWithDiagnosticsOnly!, new DiagnosticBag(), dependenciesBag: null)); private static readonly ObjectPool<BindingDiagnosticBag> s_poolWithDependenciesOnly = new ObjectPool<BindingDiagnosticBag>(() => new BindingDiagnosticBag(s_poolWithDependenciesOnly!, diagnosticBag: null, new HashSet<AssemblySymbol>())); private static readonly ObjectPool<BindingDiagnosticBag> s_poolWithConcurrent = new ObjectPool<BindingDiagnosticBag>(() => new BindingDiagnosticBag(s_poolWithConcurrent!, new DiagnosticBag(), new Roslyn.Utilities.ConcurrentSet<AssemblySymbol>())); public static readonly BindingDiagnosticBag Discarded = new BindingDiagnosticBag(null, null); private readonly ObjectPool<BindingDiagnosticBag>? _pool; private BindingDiagnosticBag(DiagnosticBag? diagnosticBag, ICollection<AssemblySymbol>? dependenciesBag) : base(diagnosticBag, dependenciesBag) { } private BindingDiagnosticBag(ObjectPool<BindingDiagnosticBag> pool, DiagnosticBag? diagnosticBag, ICollection<AssemblySymbol>? dependenciesBag) : base(diagnosticBag, dependenciesBag) { _pool = pool; } internal static BindingDiagnosticBag GetInstance() { return s_poolWithBoth.Allocate(); } internal static BindingDiagnosticBag GetInstance(bool withDiagnostics, bool withDependencies) { if (withDiagnostics) { if (withDependencies) { return GetInstance(); } return s_poolWithDiagnosticsOnly.Allocate(); } else if (withDependencies) { return s_poolWithDependenciesOnly.Allocate(); } else { return Discarded; } } internal static BindingDiagnosticBag GetInstance(BindingDiagnosticBag template) { return GetInstance(template.AccumulatesDiagnostics, template.AccumulatesDependencies); } /// <summary> /// Get an instance suitable for concurrent additions to both underlying bags. /// </summary> internal static BindingDiagnosticBag GetConcurrentInstance() { return s_poolWithConcurrent.Allocate(); } internal override void Free() { if (_pool is { } pool) { Clear(); pool.Free(this); } else { base.Free(); } } internal void AddDependencies(Symbol? symbol) { if (symbol is object && DependenciesBag is object) { AddDependencies(symbol.GetUseSiteInfo()); } } internal bool ReportUseSite(Symbol? symbol, SyntaxNode node) { return ReportUseSite(symbol, static node => node.Location, node); } internal bool ReportUseSite(Symbol? symbol, SyntaxToken token) { return ReportUseSite(symbol, static token => token.GetLocation(), token); } internal bool ReportUseSite(Symbol? symbol, Location location) => ReportUseSite(symbol, static location => location, location); internal bool ReportUseSite<TData>(Symbol? symbol, Func<TData, Location> getLocation, TData data) { if (symbol is object) { return Add(symbol.GetUseSiteInfo(), getLocation, data); } return false; } internal void AddAssembliesUsedByNamespaceReference(NamespaceSymbol ns) { if (DependenciesBag is null) { return; } addAssembliesUsedByNamespaceReferenceImpl(ns); void addAssembliesUsedByNamespaceReferenceImpl(NamespaceSymbol ns) { // Treat all assemblies contributing to this namespace symbol as used if (ns.Extent.Kind == NamespaceKind.Compilation) { foreach (var constituent in ns.ConstituentNamespaces) { addAssembliesUsedByNamespaceReferenceImpl(constituent); } } else { AssemblySymbol? containingAssembly = ns.ContainingAssembly; if (containingAssembly?.IsMissing == false) { DependenciesBag.Add(containingAssembly); } } } } protected override bool ReportUseSiteDiagnostic(DiagnosticInfo diagnosticInfo, DiagnosticBag diagnosticBag, Location location) { return Symbol.ReportUseSiteDiagnostic(diagnosticInfo, diagnosticBag, location); } internal CSDiagnosticInfo Add(ErrorCode code, Location location) { var info = new CSDiagnosticInfo(code); Add(info, location); return info; } internal CSDiagnosticInfo Add(ErrorCode code, SyntaxNode syntax, params object[] args) => Add(code, syntax.Location, args); internal CSDiagnosticInfo Add(ErrorCode code, SyntaxToken syntax, params object[] args) => Add(code, syntax.GetLocation(), args); internal CSDiagnosticInfo Add(ErrorCode code, Location location, params object[] args) { var info = new CSDiagnosticInfo(code, args); Add(info, location); return info; } internal CSDiagnosticInfo Add(ErrorCode code, Location location, ImmutableArray<Symbol> symbols, params object[] args) { var info = new CSDiagnosticInfo(code, args, symbols, ImmutableArray<Location>.Empty); Add(info, location); return info; } internal void Add(DiagnosticInfo? info, Location location) { if (info is object) { DiagnosticBag?.Add(info, location); } } } }