76 lines
2.9 KiB
C#
76 lines
2.9 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 != null && node.ThenStatement is not BeginEndBlockStatement)
|
|
{
|
|
if (node.ThenStatement.StartLine != node.StartLine || node.ScriptTokenStream.Where(t => t.Offset <= node.ThenStatement.StartOffset + node.ThenStatement.FragmentLength).Max(t => t.Line) != node.StartLine)
|
|
{
|
|
AddViolation(node.ThenStatement);
|
|
}
|
|
}
|
|
|
|
if (node.ElseStatement != null && node.ElseStatement is not BeginEndBlockStatement && node.ElseStatement is not IfStatement)
|
|
{
|
|
if (node.ElseStatement.StartLine != node.StartLine || node.ScriptTokenStream.Where(t => t.Offset <= node.ElseStatement.StartOffset + node.ElseStatement.FragmentLength).Max(t => t.Line) != node.StartLine)
|
|
{
|
|
AddViolation(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);
|
|
}
|
|
}
|
|
}
|