using System.Collections.Generic; using System.Text.RegularExpressions; using Semmle.Util; namespace Semmle.Autobuild.Shared { /// /// Direct results result from the successful application of a , /// which can later be converted to a corresponding . /// public interface IDiagnosticsResult { /// /// Produces a corresponding to this result. /// /// /// The autobuilder to use for constructing the base . /// /// /// An optional severity value which overrides the default severity of the diagnostic. /// /// The corresponding to this result. DiagnosticMessage ToDiagnosticMessage(Autobuilder builder, DiagnosticMessage.TspSeverity? severity = null) where T : AutobuildOptionsShared; } public class DiagnosticRule { /// /// The pattern against which this rule matches build output. /// public Regex Pattern { get; } /// /// Constructs a diagnostic rule for the given . /// /// public DiagnosticRule(Regex pattern) { this.Pattern = pattern; } /// /// Constructs a diagnostic rule for the given regular expression . /// /// public DiagnosticRule(string pattern) { this.Pattern = new Regex(pattern, RegexOptions.Compiled); } /// /// Used by a to /// signal that the rule has matched some build output with . /// /// The classifier which is firing the rule. /// The that resulted from applying the rule. public virtual void Fire(DiagnosticClassifier classifier, Match match) { } } public class DiagnosticClassifier { private readonly List rules; public List Results { get; } public DiagnosticClassifier() { this.rules = new List(); this.Results = new List(); } /// /// Adds to this classifier. /// /// The rule to add. protected void AddRule(DiagnosticRule rule) { this.rules.Add(rule); } /// /// Applies all of this classifier's rules to to see which match. /// /// The line to which the rules should be applied to. public void ClassifyLine(string line) { this.rules.ForEach(rule => { var match = rule.Pattern.Match(line); if (match.Success) { rule.Fire(this, match); } }); } } }