diff --git a/SQLLinter/Common/BaseRuleVisitor.cs b/SQLLinter/Common/BaseRuleVisitor.cs index 36d7ab3..892fc97 100644 --- a/SQLLinter/Common/BaseRuleVisitor.cs +++ b/SQLLinter/Common/BaseRuleVisitor.cs @@ -55,14 +55,14 @@ public abstract class BaseRuleVisitor : TSqlFragmentVisitor, IRule _violations.Add(violation); } - protected void AddViolation(string RuleName, string Message, int Line, int Column) + protected void AddViolation(string RuleName, string Template, int Line, int Column, params string[] param) { - _violations.Add(new(RuleName, Message, Line, Column)); + _violations.Add(new(RuleName, Template, Line, Column, param)); } protected void AddViolation(TSqlFragment node, params string[] param) { - AddViolation(Name, this.GetText(param), GetLineNumber(node), GetColumnNumber(node)); + _violations.Add(new(this.Name, this.Text, GetLineNumber(node), GetColumnNumber(node), param)); } protected string GetText(params string[] param) diff --git a/SQLLinter/Common/IReporter.cs b/SQLLinter/Common/IReporter.cs index 5f2bd94..efc65bb 100644 --- a/SQLLinter/Common/IReporter.cs +++ b/SQLLinter/Common/IReporter.cs @@ -4,5 +4,5 @@ public interface IReporter : IBaseReporter { void ReportViolation(IRuleViolation violation); - void ReportViolation(string fileName, int line, int column, RuleViolationSeverity severity, string ruleName, string violationText); + void ReportViolation(string fileName, int line, int column, RuleViolationSeverity severity, string ruleName, string template, params string[] param); } \ No newline at end of file diff --git a/SQLLinter/Common/Violation.cs b/SQLLinter/Common/Violation.cs index a635232..4b797ce 100644 --- a/SQLLinter/Common/Violation.cs +++ b/SQLLinter/Common/Violation.cs @@ -1,4 +1,4 @@ namespace SQLLinter.Common { - public record Violation(string RuleName, string Message, int Line, int Column); + public record Violation(string RuleName, string Template, int Line, int Column, string[] Params); } diff --git a/SQLLinter/Infrastructure/Parser/SqlRuleVisitor.cs b/SQLLinter/Infrastructure/Parser/SqlRuleVisitor.cs index eb04ec4..dcdaa1b 100644 --- a/SQLLinter/Infrastructure/Parser/SqlRuleVisitor.cs +++ b/SQLLinter/Infrastructure/Parser/SqlRuleVisitor.cs @@ -76,7 +76,7 @@ public class SqlRuleVisitor : IRuleVisitor } } - violations.ForEach(t => _reporter.ReportViolation(filePath, t.Line, t.Column, rule.Severity, t.RuleName, t.Message)); + violations.ForEach(t => _reporter.ReportViolation(filePath, t.Line, t.Column, rule.Severity, t.RuleName, t.Template, t.Params)); } private static bool VisitorIsBlackListedForDynamicSql(IRule visitor) @@ -109,7 +109,15 @@ public class SqlRuleVisitor : IRuleVisitor if (!globalRulesOnLine.Any()) { - _reporter.ReportViolation(new RuleViolation(sqlPath, "invalid-syntax", error.Message, error.Line, error.Column, RuleViolationSeverity.Critical)); + _reporter.ReportViolation(new RuleViolation() + { + FileName = sqlPath, + RuleName = "invalid-syntax", + Text = error.Message, + Line = error.Line, + Column = error.Column, + Severity = RuleViolationSeverity.Critical + }); if (updatedExitCode) { continue; diff --git a/SQLLinter/Infrastructure/Reporters/Reporter.cs b/SQLLinter/Infrastructure/Reporters/Reporter.cs index 04f4b39..f3b9114 100644 --- a/SQLLinter/Infrastructure/Reporters/Reporter.cs +++ b/SQLLinter/Infrastructure/Reporters/Reporter.cs @@ -7,15 +7,22 @@ namespace SQLLinter.Infrastructure.Reporters; public class Reporter : IReporter { private readonly List _log = new(); + private readonly bool _useLogging; public int? FixedCount { get; set; } + private readonly ConcurrentBag ruleViolations = new(); public List Violations => ruleViolations.ToList(); + public Reporter(bool useLogging = false) + { + _useLogging = useLogging; + } + public virtual void Report(string message) { - _log.Add(message); + if (_useLogging) _log.Add(message); } public List GetLog() => _log; @@ -34,8 +41,17 @@ public class Reporter : IReporter Report(violation.ToString()); } - public void ReportViolation(string fileName, int line, int column, RuleViolationSeverity severity, string ruleName, string violationText) + public void ReportViolation(string fileName, int line, int column, RuleViolationSeverity severity, string ruleName, string template, params string[] param) { - ReportViolation(new RuleViolation(fileName, ruleName, violationText, line, column, severity)); + ReportViolation(new RuleTemplateViolation() + { + FileName = fileName, + RuleName = ruleName, + RuleTemplate = template, + Line = line, + Column = column, + Severity = severity, + Params = param.ToList(), + }); } } diff --git a/SQLLinter/Infrastructure/Rules/ConditionalBeginEndRule.cs b/SQLLinter/Infrastructure/Rules/ConditionalBeginEndRule.cs index d704eec..7b758fb 100644 --- a/SQLLinter/Infrastructure/Rules/ConditionalBeginEndRule.cs +++ b/SQLLinter/Infrastructure/Rules/ConditionalBeginEndRule.cs @@ -19,7 +19,7 @@ public class ConditionalBeginEndRule : BaseRuleVisitor, IRule { if (node.ThenStatement is not BeginEndBlockStatement) { - AddViolation(Name, Text, GetLineNumber(node), GetColumnNumber(node)); + AddViolation(node); } if (node.ElseStatement != null && node.ElseStatement is not BeginEndBlockStatement && node.ElseStatement is not IfStatement) diff --git a/SQLLinter/Infrastructure/Rules/IndexHintRule.cs b/SQLLinter/Infrastructure/Rules/IndexHintRule.cs index 9e9067c..6cc4e51 100644 --- a/SQLLinter/Infrastructure/Rules/IndexHintRule.cs +++ b/SQLLinter/Infrastructure/Rules/IndexHintRule.cs @@ -11,7 +11,7 @@ public class IndexHintRule : BaseRuleVisitor { if (node.HintKind == TableHintKind.Index) { - AddViolation(Name, Text, GetLineNumber(node), GetColumnNumber(node)); + AddViolation(node); } } } diff --git a/SQLLinter/Infrastructure/Rules/InsertValuesInsteadOfSelectRule.cs b/SQLLinter/Infrastructure/Rules/InsertValuesInsteadOfSelectRule.cs index 834363e..affda37 100644 --- a/SQLLinter/Infrastructure/Rules/InsertValuesInsteadOfSelectRule.cs +++ b/SQLLinter/Infrastructure/Rules/InsertValuesInsteadOfSelectRule.cs @@ -18,7 +18,7 @@ public class InsertValuesInsteadOfSelectRule : BaseRuleVisitor // Если в SELECT нет таблиц (т.е. просто SELECT 1,2,3) if (query.FromClause == null || query.FromClause.TableReferences.Count == 0) { - AddViolation(Name, Text, GetLineNumber(node), GetColumnNumber(node)); + AddViolation(node); } } } diff --git a/SQLLinter/Infrastructure/Rules/KeywordCapitalizationRule.cs b/SQLLinter/Infrastructure/Rules/KeywordCapitalizationRule.cs index 7df162e..ea82317 100644 --- a/SQLLinter/Infrastructure/Rules/KeywordCapitalizationRule.cs +++ b/SQLLinter/Infrastructure/Rules/KeywordCapitalizationRule.cs @@ -33,7 +33,7 @@ public class KeywordCapitalizationRule : BaseRuleVisitor, IRule var tabsOnLine = ColumnNumberCalculator.CountTabsBeforeToken(token.Line, index, node.ScriptTokenStream); var column = ColumnNumberCalculator.GetColumnNumberBeforeToken(tabsOnLine, token); - AddViolation(Name, GetText(token.Text), GetLineNumber(token), column + dynamicSQLAdjustment); + AddViolation(Name, Text, GetLineNumber(token), column + dynamicSQLAdjustment, token.Text); } } diff --git a/SQLLinter/Infrastructure/Rules/MultiTableAliasRule.cs b/SQLLinter/Infrastructure/Rules/MultiTableAliasRule.cs index d410be7..5b9a01a 100644 --- a/SQLLinter/Infrastructure/Rules/MultiTableAliasRule.cs +++ b/SQLLinter/Infrastructure/Rules/MultiTableAliasRule.cs @@ -34,7 +34,7 @@ public class MultiTableAliasRule : BaseRuleVisitor, IRule tableName = SQLHelpers.ObjectGetFullName(namedTable.SchemaObject); } - AddViolation(Name, GetText(tableName), GetLineNumber(childNode), column + dynamicSqlAdjustment); + AddViolation(Name, Text, GetLineNumber(childNode), column + dynamicSqlAdjustment, tableName); } var childTableJoinVisitor = new ChildTableJoinVisitor(); diff --git a/SQLLinter/Infrastructure/Rules/ProcedureLoggingRule.cs b/SQLLinter/Infrastructure/Rules/ProcedureLoggingRule.cs index 14c0fc8..537e745 100644 --- a/SQLLinter/Infrastructure/Rules/ProcedureLoggingRule.cs +++ b/SQLLinter/Infrastructure/Rules/ProcedureLoggingRule.cs @@ -79,7 +79,7 @@ public class ProcedureLoggingReturnRule : BaseRuleVisitor if ((hasDebugLog || hasLabelFinish) || hasReturn) { - returnPositions.ForEach(t => AddViolation(Name, GetText(name), t.Line, t.Column)); + returnPositions.ForEach(t => AddViolation(Name, Text, t.Line, t.Column, name)); } } diff --git a/SQLLinter/Infrastructure/Rules/RuleViolations/RuleViolation.cs b/SQLLinter/Infrastructure/Rules/RuleViolations/RuleViolation.cs index 5b6c6ae..cd7c420 100644 --- a/SQLLinter/Infrastructure/Rules/RuleViolations/RuleViolation.cs +++ b/SQLLinter/Infrastructure/Rules/RuleViolations/RuleViolation.cs @@ -4,46 +4,25 @@ namespace SQLLinter.Infrastructure.Rules.RuleViolations { public class RuleViolation : IRuleViolation { - public RuleViolation(string fileName, string ruleName, string text, int startLine, int startColumn, RuleViolationSeverity severity) - { - FileName = fileName; - RuleName = ruleName; - Text = text; - Line = startLine; - Column = startColumn; - Severity = severity; - } + required public string FileName { get; init; } - public RuleViolation(string fileName, string ruleName, int startLine, int startColumn) - { - FileName = fileName; - RuleName = ruleName; - Line = startLine; - Column = startColumn; - } + required public int Column { get; set; } - public RuleViolation(string ruleName, int startLine, int startColumn) - { - RuleName = ruleName; - Line = startLine; - Column = startColumn; - } + required public int Line { get; set; } - public int Column { get; set; } + required public string RuleName { get; init; } - public string FileName { get; set; } + required public RuleViolationSeverity Severity { get; init; } - public int Line { get; set; } + virtual public string Text { get; set; } + } - public string RuleName { get; set; } + public class RuleTemplateViolation : RuleViolation + { + override public string Text => string.Format(RuleTemplate, Params.ToArray()); - public RuleViolationSeverity Severity { get; set; } + required public string RuleTemplate { get; init; } - public string Text { get; set; } - - public override string ToString() - { - return $@"{Severity.ToString().ToUpper()}: L{Line} C{Column} {FileName} ""{Text}"""; - } + public List Params { get; set; } = new(); } }