using Microsoft.SqlServer.TransactSql.ScriptDom; using SQLLinter.Common; using SQLLinter.Core; using SQLLinter.Infrastructure.Rules.Common; using System.Text.RegularExpressions; namespace SQLLinter.Infrastructure.Rules; public class KeywordCapitalizationRule : BaseRuleVisitor, IRule { public override string Text => "Ожидается, что ключевое слово TSQL будет написано в верхнем регистре: {0}"; public override void Visit(TSqlScript node) { var typesToUpcase = Constants.TSqlKeywords.Concat(Constants.TSqlDataTypes).ToArray(); for (var index = 0; index < node.ScriptTokenStream?.Count; index++) { var token = node.ScriptTokenStream[index]; if (!typesToUpcase.Contains(token.Text, StringComparer.CurrentCultureIgnoreCase)) { continue; } if (IsUpperCase(token.Text)) { continue; } var dynamicSQLAdjustment = GetDynamicSqlColumnOffset(token); // получить количество всех вкладок в строке, которые встречаются до последнего токена в этом узле var tabsOnLine = ColumnNumberCalculator.CountTabsBeforeToken(token.Line, index, node.ScriptTokenStream); var column = ColumnNumberCalculator.GetColumnNumberBeforeToken(tabsOnLine, token); AddViolation(Name, Text, GetLineNumber(token), column + dynamicSQLAdjustment, token.Text); } } public override void FixViolation(List fileLines, IRuleViolation ruleViolation, FileLineActions actions) { var lineIndex = ruleViolation.Line - 1; var line = fileLines[lineIndex]; var startCharIndex = ColumnNumberCalculator.GetIndex(line, ruleViolation.Column); if (startCharIndex != -1) { var errorWord = new Regex(@"\w+").Matches(line[startCharIndex..]).First().Value; actions.RepaceInlineAt(lineIndex, startCharIndex, errorWord.ToUpper()); } } private static bool IsUpperCase(string input) { return input.All(t => !char.IsLetter(t) || char.IsUpper(t)); } }