Files
SQLLint/SQLLinter/Infrastructure/Rules/ConditionalBeginEndRule.cs

70 lines
2.4 KiB
C#

using Microsoft.SqlServer.TransactSql.ScriptDom;
using SQLLinter.Common;
using SQLLinter.Common.Helpers;
using System.Text.RegularExpressions;
namespace SQLLinter.Infrastructure.Rules;
/// <summary>
/// Ожидается наличие BEGIN - END в блоке IF
/// </summary>
public class ConditionalBeginEndRule : BaseRuleVisitor, IRule
{
private readonly Regex IsWhiteSpaceOrSemiColon = new Regex(@"\s|;", RegexOptions.Compiled);
public override string Text => "Ожидается наличие BEGIN - END в блоке IF";
public override void Visit(IfStatement node)
{
if (node.ThenStatement is not BeginEndBlockStatement)
{
AddViolation(node);
}
if (node.ElseStatement != null && node.ElseStatement is not BeginEndBlockStatement && node.ElseStatement is not IfStatement)
{
AddViolation(Name, Text, GetLineNumber(node.ElseStatement), GetColumnNumber(node.ElseStatement));
}
}
public override void FixViolation(List<string> fileLines, IRuleViolation ruleViolation, FileLineActions actions)
{
var ifNode = FixHelpers.FindViolatingNode<IfStatement>(fileLines, ruleViolation);
TSqlStatement statement;
if (ifNode == null)
{
(statement, ifNode) = FindElse(fileLines, ruleViolation);
}
else
{
statement = ifNode.ThenStatement;
}
var stream = statement.ScriptTokenStream;
var indent = FixHelpers.GetIndent(fileLines, ifNode);
var beingLine = stream[statement.FirstTokenIndex].Line - 1;
var ifNodeLastToken = stream[statement.LastTokenIndex];
var endLine = stream[statement.LastTokenIndex].Line;
if (statement.StartLine == ifNodeLastToken.Line)
{
var index = statement.LastTokenIndex;
actions.InsertInLine(statement.StartLine - 1, stream[index].Column, " END");
actions.InsertInLine(statement.StartLine - 1, statement.StartColumn - 1, "BEGIN ");
}
else
{
actions.Insert(endLine, $"{indent}END");
actions.Insert(beingLine, $"{indent}BEGIN");
}
static (TSqlStatement, IfStatement) FindElse(List<string> fileLines, IRuleViolation ruleViolation)
{
return FixHelpers.FindViolatingNode<IfStatement, TSqlStatement>(
fileLines, ruleViolation, x => x.ElseStatement);
}
}
}