/* Copyright 2010-2018 Jesse McGrew
*
* This file is part of ZILF.
*
* ZILF is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ZILF is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ZILF. If not, see .
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using JetBrains.Annotations;
namespace Zilf.Diagnostics
{
sealed class DiagnosticManager
{
const int MaxErrorCount = 100;
[NotNull]
readonly List diagnostics = new List();
[NotNull]
readonly List suppressedDiagnostics = new List();
[NotNull]
readonly HashSet suppressions = new HashSet();
bool suppressAllTheThings = false;
[NotNull]
public IReadOnlyCollection Diagnostics => diagnostics;
public int ErrorCount => Diagnostics.Count(d => d.Severity == Severity.Error || d.Severity == Severity.Fatal);
public int WarningCount => Diagnostics.Count(d => d.Severity == Severity.Warning);
public int SuppressedWarningCount => suppressedDiagnostics.Count(d => d.Severity == Severity.Warning);
public bool WarningsAsErrors { get; set; }
public bool SuppressNoisyWarnings { get; set; }
[NotNull]
public IDiagnosticFormatter Formatter { get; }
[NotNull]
public TextWriter OutputWriter { get; }
public event EventHandler TooManyErrors;
public DiagnosticManager([CanBeNull] IDiagnosticFormatter formatter = null, [CanBeNull] TextWriter outputWriter = null)
{
Formatter = formatter ?? new DefaultDiagnosticFormatter();
OutputWriter = outputWriter ?? Console.Error;
}
public void Suppress([NotNull] string code)
{
if (!suppressAllTheThings)
suppressions.Add(code);
}
public void Suppress([NotNull, ItemNotNull] IEnumerable codes)
{
if (!suppressAllTheThings)
suppressions.UnionWith(codes);
}
public void SuppressAll()
{
suppressAllTheThings = true;
suppressions.Clear();
}
public void SuppressNone()
{
suppressAllTheThings = false;
suppressions.Clear();
}
public void Handle([NotNull] Diagnostic diag)
{
if (WarningsAsErrors && diag.Severity == Severity.Warning)
{
diag = diag.WithSeverity(Severity.Error);
}
diagnostics.Add(diag);
if (diag.Severity == Severity.Error && ErrorCount >= MaxErrorCount)
{
TooManyErrors?.Invoke(this, EventArgs.Empty);
}
if (IsSuppressed(diag))
{
suppressedDiagnostics.Add(diag);
}
else
{
OutputWriter.WriteLine(Formatter.Format(diag));
}
}
private bool IsSuppressed([NotNull] Diagnostic diag)
{
if (diag.Severity >= Severity.Error)
return false;
if (SuppressNoisyWarnings && diag.Severity == Severity.Warning && diag.Noisy)
return true;
return suppressAllTheThings || suppressions.Contains(diag.Code);
}
}
}