using Microsoft.SqlServer.TransactSql.ScriptDom; using SQLLinter.Common; using SQLLinter.Common.Helpers; namespace SQLLinter.Infrastructure.Rules; public class HeaderCommentRule : BaseRuleVisitor { public override string Text => "У процедур/функций/триггеров должна быть шапка-комментарий с автором, департаментом, назначением: {0}"; public override void Visit(CreateProcedureStatement node) => private_visit(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name)); public override void Visit(CreateOrAlterProcedureStatement node) => private_visit(node, SQLHelpers.ObjectGetFullName(node.ProcedureReference.Name)); public override void Visit(CreateFunctionStatement node) => private_visit(node, SQLHelpers.ObjectGetFullName(node.Name)); public override void Visit(CreateOrAlterFunctionStatement node) => private_visit(node, SQLHelpers.ObjectGetFullName(node.Name)); public override void Visit(CreateTriggerStatement node) => private_visit(node, SQLHelpers.ObjectGetFullName(node.Name)); public override void Visit(CreateOrAlterTriggerStatement node) => private_visit(node, SQLHelpers.ObjectGetFullName(node.Name)); public override void Visit(CreateViewStatement node) => private_visit(node, SQLHelpers.ObjectGetFullName(node.SchemaObjectName)); public override void Visit(CreateOrAlterViewStatement node) => private_visit(node, SQLHelpers.ObjectGetFullName(node.SchemaObjectName)); private void private_visit(TSqlFragment node, string name) { var prevTokenIndex = node.FirstTokenIndex; TSqlParserToken? prevToken = null; while (prevTokenIndex > 0) { prevTokenIndex -= 1; prevToken = node.ScriptTokenStream[prevTokenIndex]; if (prevToken.TokenType != TSqlTokenType.WhiteSpace) break; } if (prevToken == null || prevToken.TokenType != TSqlTokenType.SingleLineComment && prevToken.TokenType != TSqlTokenType.MultilineComment ) { 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); } } } }