From 7fb11364c45c0ce12c5c1bf2dc4c81c1c678c8bb Mon Sep 17 00:00:00 2001 From: FrigaT Date: Mon, 29 Dec 2025 01:10:17 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=BE=20=D1=84=D0=BE=D1=80=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B4=D0=B5=D1=82=D0=B0=D0=BB=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=BA=D0=B8:=20=D0=B7=D0=B0=D0=B2=D0=B8=D1=81?= =?UTF-8?q?=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D1=8C=20=D0=BE=D1=82=20=D1=81?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=BA,=20=D0=B0=20=D0=BD=D0=B5=20=D0=BE?= =?UTF-8?q?=D1=82=20=D1=80=D0=BE=D0=B4=D0=B8=D1=82=D0=B5=D0=BB=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SQLLinter.CLI/Program.cs | 1 + SQLLinter/Common/BaseRuleVisitor.cs | 11 ++++++---- SQLLinter/Common/IRule.cs | 1 + .../Infrastructure/Parser/SqlRuleVisitor.cs | 4 ++-- .../Rules/AlterProcedureInDboRule.cs | 2 +- .../Rules/CreateProcedureInDboRule.cs | 4 ++-- .../Rules/ExecuteAsOwnerRule.cs | 2 +- .../Infrastructure/Rules/HeaderCommentRule.cs | 22 ++++++++++++++++--- .../Infrastructure/Rules/InsertStarRule.cs | 2 +- .../Rules/ProcedureLoggingRule.cs | 4 ++-- 10 files changed, 37 insertions(+), 16 deletions(-) diff --git a/SQLLinter.CLI/Program.cs b/SQLLinter.CLI/Program.cs index 9153c39..487b27c 100644 --- a/SQLLinter.CLI/Program.cs +++ b/SQLLinter.CLI/Program.cs @@ -43,6 +43,7 @@ namespace SQLLinter.CLI ["UpdateWhere"] = Common.RuleViolationSeverity.Critical, ["UpperLower"] = Common.RuleViolationSeverity.Critical, ["SetVariable"] = Common.RuleViolationSeverity.Critical, + ["CreateProcedureInDbo"] = Common.RuleViolationSeverity.Warning, }, GenerateDetails = true, }; diff --git a/SQLLinter/Common/BaseRuleVisitor.cs b/SQLLinter/Common/BaseRuleVisitor.cs index 3b48447..c0e8455 100644 --- a/SQLLinter/Common/BaseRuleVisitor.cs +++ b/SQLLinter/Common/BaseRuleVisitor.cs @@ -83,8 +83,12 @@ public abstract class BaseRuleVisitor : TSqlFragmentVisitor, IRule return string.Format(this.Text, param); } + private TSqlFragment? FindContextBlock(TSqlFragment node) { + if (_parents == null) return null; + return node; + var current = node; while (current != null) @@ -139,7 +143,6 @@ public abstract class BaseRuleVisitor : TSqlFragmentVisitor, IRule } - // Вспомогательные классы public class ExtractedBlock { @@ -165,13 +168,13 @@ public abstract class BaseRuleVisitor : TSqlFragmentVisitor, IRule protected ExtractedBlock? ExtractBlock(TSqlFragment? node, TSqlFragment errorNode) { - if (node == null || node.ScriptTokenStream == null) + if (node == null || errorNode.ScriptTokenStream == null) return null; - var endLine = node.ScriptTokenStream.Where(t => t.Offset < node.StartOffset + node.FragmentLength).Max(t => t.Line) + 2; + var endLine = errorNode.ScriptTokenStream.Where(t => t.Offset < node.StartOffset + node.FragmentLength).Max(t => t.Line) + 2; // 1. Получаем токены для блока - var tokens = node.ScriptTokenStream + var tokens = errorNode.ScriptTokenStream .Where(t => t.Line >= node.StartLine - 2 && t.Line <= endLine) .ToList(); diff --git a/SQLLinter/Common/IRule.cs b/SQLLinter/Common/IRule.cs index b0cb822..41d692e 100644 --- a/SQLLinter/Common/IRule.cs +++ b/SQLLinter/Common/IRule.cs @@ -13,5 +13,6 @@ public interface IRule int DynamicSqlStartLine { get; set; } IEnumerable Analyze(TSqlFragment fragment); + void SetParents(Dictionary? parents); } \ No newline at end of file diff --git a/SQLLinter/Infrastructure/Parser/SqlRuleVisitor.cs b/SQLLinter/Infrastructure/Parser/SqlRuleVisitor.cs index 68be2eb..90a16a9 100644 --- a/SQLLinter/Infrastructure/Parser/SqlRuleVisitor.cs +++ b/SQLLinter/Infrastructure/Parser/SqlRuleVisitor.cs @@ -3,7 +3,6 @@ using SQLLinter.Common; using SQLLinter.Core.Interfaces; using SQLLinter.Infrastructure.Configuration.Overrides; using SQLLinter.Infrastructure.Interfaces; -using SQLLinter.Infrastructure.Rules; using SQLLinter.Infrastructure.Rules.RuleExceptions; using SQLLinter.Infrastructure.Rules.RuleViolations; using System.Data; @@ -39,7 +38,8 @@ public class SqlRuleVisitor : IRuleVisitor if (sqlFragment == null) return; - Dictionary? parentMap = generateDetails ? ParentMapBuilder.Build(sqlFragment) : null; + //Dictionary? parentMap = generateDetails ? ParentMapBuilder.Build(sqlFragment) : null; + Dictionary? parentMap = new Dictionary(); var ruleExceptions = ignoredRules as IRuleException[] ?? ignoredRules.ToArray(); if (errors.Any()) diff --git a/SQLLinter/Infrastructure/Rules/AlterProcedureInDboRule.cs b/SQLLinter/Infrastructure/Rules/AlterProcedureInDboRule.cs index 711fff8..878a316 100644 --- a/SQLLinter/Infrastructure/Rules/AlterProcedureInDboRule.cs +++ b/SQLLinter/Infrastructure/Rules/AlterProcedureInDboRule.cs @@ -12,7 +12,7 @@ public class AlterProcedureInDboRule : BaseRuleVisitor { if (node.ProcedureReference.Name.SchemaIdentifier?.Value.Equals("dbo", StringComparison.OrdinalIgnoreCase) == true) { - AddViolation(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name)); + AddViolation(node.ProcedureReference.Name.SchemaIdentifier, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name)); } } } diff --git a/SQLLinter/Infrastructure/Rules/CreateProcedureInDboRule.cs b/SQLLinter/Infrastructure/Rules/CreateProcedureInDboRule.cs index 06cd809..b1d9cde 100644 --- a/SQLLinter/Infrastructure/Rules/CreateProcedureInDboRule.cs +++ b/SQLLinter/Infrastructure/Rules/CreateProcedureInDboRule.cs @@ -12,14 +12,14 @@ public class CreateProcedureInDboRule : BaseRuleVisitor { if (node.ProcedureReference.Name.SchemaIdentifier?.Value.Equals("dbo", StringComparison.OrdinalIgnoreCase) == true) { - AddViolation(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name)); + AddViolation(node.ProcedureReference.Name.SchemaIdentifier, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name)); } } public override void Visit(CreateOrAlterProcedureStatement node) { if (node.ProcedureReference.Name.SchemaIdentifier?.Value.Equals("dbo", StringComparison.OrdinalIgnoreCase) == true) { - AddViolation(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name)); + AddViolation(node.ProcedureReference.Name.SchemaIdentifier, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name)); } } } diff --git a/SQLLinter/Infrastructure/Rules/ExecuteAsOwnerRule.cs b/SQLLinter/Infrastructure/Rules/ExecuteAsOwnerRule.cs index 5995a9a..1e511ed 100644 --- a/SQLLinter/Infrastructure/Rules/ExecuteAsOwnerRule.cs +++ b/SQLLinter/Infrastructure/Rules/ExecuteAsOwnerRule.cs @@ -25,6 +25,6 @@ public class ExecuteAsOwnerRule : BaseRuleVisitor } } - AddViolation(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name)); + AddViolation(node.ProcedureReference.Name, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name)); } } diff --git a/SQLLinter/Infrastructure/Rules/HeaderCommentRule.cs b/SQLLinter/Infrastructure/Rules/HeaderCommentRule.cs index a28670f..f2cdae9 100644 --- a/SQLLinter/Infrastructure/Rules/HeaderCommentRule.cs +++ b/SQLLinter/Infrastructure/Rules/HeaderCommentRule.cs @@ -20,9 +20,9 @@ public class HeaderCommentRule : BaseRuleVisitor public override void Visit(CreateOrAlterTriggerStatement node) => private_visit(node, SQLHelpers.ObjectGetFullName(node.Name)); - public override void Visit(CreateViewStatement node) => private_visit(node, ""); + public override void Visit(CreateViewStatement node) => private_visit(node, SQLHelpers.ObjectGetFullName(node.SchemaObjectName)); - public override void Visit(CreateOrAlterViewStatement node) => private_visit(node, ""); + public override void Visit(CreateOrAlterViewStatement node) => private_visit(node, SQLHelpers.ObjectGetFullName(node.SchemaObjectName)); private void private_visit(TSqlFragment node, string name) { @@ -40,7 +40,23 @@ public class HeaderCommentRule : BaseRuleVisitor prevToken.TokenType != TSqlTokenType.SingleLineComment && prevToken.TokenType != TSqlTokenType.MultilineComment ) { - AddViolation(node, name); + if (node is ProcedureStatementBody proc) + { + AddViolation(proc.ProcedureReference.Name, name); + } + else if (node is ViewStatementBody view) + { + AddViolation(view.SchemaObjectName, name); + + } + else if (node is TriggerStatementBody tr) + { + AddViolation(tr.Name, name); + } + else + { + AddViolation(node, name); + } } } } diff --git a/SQLLinter/Infrastructure/Rules/InsertStarRule.cs b/SQLLinter/Infrastructure/Rules/InsertStarRule.cs index 2578f9b..246661d 100644 --- a/SQLLinter/Infrastructure/Rules/InsertStarRule.cs +++ b/SQLLinter/Infrastructure/Rules/InsertStarRule.cs @@ -11,7 +11,7 @@ public class InsertStarRule : BaseRuleVisitor { if (node.InsertSpecification.Columns.Count == 0) // INSERT без перечисления колонок { - AddViolation(node); + AddViolation(node.InsertSpecification.Target); } } } \ No newline at end of file diff --git a/SQLLinter/Infrastructure/Rules/ProcedureLoggingRule.cs b/SQLLinter/Infrastructure/Rules/ProcedureLoggingRule.cs index 537e745..9322241 100644 --- a/SQLLinter/Infrastructure/Rules/ProcedureLoggingRule.cs +++ b/SQLLinter/Infrastructure/Rules/ProcedureLoggingRule.cs @@ -12,7 +12,7 @@ public class ProcedureLoggingRule : BaseRuleVisitor public override void Visit(CreateOrAlterProcedureStatement node) => check(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name)); public override void Visit(AlterProcedureStatement node) => check(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name)); - private void check(TSqlStatement node, string name) + private void check(ProcedureStatementBody node, string name) { var tokens = node.ScriptTokenStream; @@ -35,7 +35,7 @@ public class ProcedureLoggingRule : BaseRuleVisitor if (!hasDebugLog || !hasLabelFinish) { - AddViolation(node, name); + AddViolation(node.ProcedureReference.Name, name); } } }