Добавьте файлы проекта.
This commit is contained in:
73
SQLLinter/Infrastructure/Rules/SemicolonTerminationRule.cs
Normal file
73
SQLLinter/Infrastructure/Rules/SemicolonTerminationRule.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user