Добавьте файлы проекта.

This commit is contained in:
2025-12-07 08:52:05 +03:00
parent 95344cd7a7
commit 226b6b6b21
118 changed files with 5249 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
using Microsoft.SqlServer.TransactSql.ScriptDom;
using SQLLinter.Common;
using SQLLinter.Infrastructure.Rules.Common;
using System.Text.RegularExpressions;
namespace SQLLinter.Infrastructure.Rules;
public class SemicolonTerminationRule : BaseRuleVisitor, IRule
{
private readonly IList<TSqlFragment> waitForStatements = new List<TSqlFragment>();
private readonly IList<TSqlFragment> functionReturnTypeSelectStatements = new List<TSqlFragment>();
private static Regex WhiteSpaceRegex = new Regex(@"\s", RegexOptions.Compiled);
private static Regex AllWhiteSpaceRegex = new Regex(@"^\s$", RegexOptions.Compiled);
// не принудительно завершать эти операторы точкой с запятой
private readonly Type[] typesToSkip =
{
typeof(BeginEndBlockStatement),
typeof(GoToStatement),
typeof(IndexDefinition),
typeof(LabelStatement),
typeof(WhileStatement),
typeof(IfStatement),
typeof(CreateViewStatement)
};
public override string Text => "Оператор не заканчивается точкой с запятой";
public override void Visit(WaitForStatement node)
{
waitForStatements.Add(node.Statement);
}
public override void Visit(CreateFunctionStatement node)
{
if (node.ReturnType is SelectFunctionReturnType returnType)
{
functionReturnTypeSelectStatements.Add(returnType.SelectStatement);
}
}
public override void Visit(TSqlStatement node)
{
if (Array.IndexOf(typesToSkip, node.GetType()) > -1 ||
EndsWithSemicolon(node) ||
waitForStatements.Contains(node) ||
functionReturnTypeSelectStatements.Contains(node))
{
return;
}
var dynamicSqlColumnOffset = GetDynamicSqlColumnOffset(node);
var (lastToken, column) = GetLastTokenAndColumn(node);
AddViolation(Name, Text, GetLineNumber(lastToken), column + dynamicSqlColumnOffset);
}
private static (TSqlParserToken, int) GetLastTokenAndColumn(TSqlStatement node)
{
var lastToken = node.ScriptTokenStream[node.LastTokenIndex];
var tabsOnLine = ColumnNumberCalculator.CountTabsBeforeToken(lastToken.Line, node.LastTokenIndex, node.ScriptTokenStream);
var column = ColumnNumberCalculator.GetColumnNumberAfterToken(tabsOnLine, lastToken);
return (lastToken, column);
}
private static bool EndsWithSemicolon(TSqlFragment node)
{
return node.ScriptTokenStream[node.LastTokenIndex].TokenType == TSqlTokenType.Semicolon
|| node.ScriptTokenStream[node.LastTokenIndex + 1].TokenType == TSqlTokenType.Semicolon;
}
}