in DevSkim-DotNet/Microsoft.DevSkim/Ruleset.cs [166:326]
public ConvertedOatRule? DevSkimRuleToConvertedOatRule(Rule rule)
{
if (rule == null)
return null;
var clauses = new List<Clause>();
int clauseNumber = 0;
var expression = new StringBuilder("(");
foreach (var pattern in rule.Patterns ?? new List<SearchPattern>())
{
if (pattern.Pattern != null)
{
var scopes = pattern.Scopes ?? new PatternScope[] { PatternScope.All };
var modifiers = pattern.Modifiers ?? Array.Empty<string>();
if (clauses.Where(x => x is ScopedRegexClause src &&
src.Arguments.SequenceEqual(modifiers) && src.Scopes.SequenceEqual(scopes)) is IEnumerable<Clause> filteredClauses &&
filteredClauses.Any() && filteredClauses.First().Data is List<string> found)
{
found.Add(pattern.Pattern);
}
else
{
clauses.Add(new ScopedRegexClause(scopes)
{
Label = clauseNumber.ToString(CultureInfo.InvariantCulture),
Data = new List<string>() { pattern.Pattern },
Capture = true,
Arguments = pattern.Modifiers?.ToList() ?? new List<string>()
});
if (clauseNumber > 0)
{
expression.Append(" OR ");
}
expression.Append(clauseNumber);
clauseNumber++;
}
}
}
if (clauses.Any())
{
expression.Append(')');
}
else
{
return new ConvertedOatRule(rule.Id, rule);
}
foreach (var condition in rule.Conditions ?? new List<SearchCondition>())
{
if (condition.Pattern?.Pattern != null)
{
if (condition.SearchIn is null || condition.SearchIn.Equals("finding-only", StringComparison.InvariantCultureIgnoreCase))
{
clauses.Add(new WithinClause()
{
Data = new List<string>() { condition.Pattern.Pattern },
Label = clauseNumber.ToString(CultureInfo.InvariantCulture),
Invert = condition.NegateFinding,
Arguments = condition.Pattern.Modifiers?.ToList() ?? new List<string>(),
FindingOnly = true,
});
expression.Append(" AND ");
expression.Append(clauseNumber);
clauseNumber++;
}
else if (condition.SearchIn.StartsWith("finding-region", StringComparison.InvariantCultureIgnoreCase))
{
var argList = new List<int>();
Match m = searchInRegex.Match(condition.SearchIn);
if (m.Success)
{
for (int i = 1; i < m.Groups.Count; i++)
{
if (int.TryParse(m.Groups[i].Value, out int value))
{
argList.Add(value);
}
else
{
break;
}
}
}
if (argList.Count == 2)
{
clauses.Add(new WithinClause()
{
Data = new List<string>() { condition.Pattern.Pattern },
Label = clauseNumber.ToString(CultureInfo.InvariantCulture),
Invert = condition.NegateFinding,
Arguments = condition.Pattern.Modifiers?.ToList() ?? new List<string>(),
Before = argList[0],
After = argList[1]
});
expression.Append(" AND ");
expression.Append(clauseNumber);
clauseNumber++;
}
}
else if (condition.SearchIn.Equals("same-line", StringComparison.InvariantCultureIgnoreCase))
{
clauses.Add(new WithinClause()
{
Data = new List<string>() { condition.Pattern.Pattern },
Label = clauseNumber.ToString(CultureInfo.InvariantCulture),
Invert = condition.NegateFinding,
Arguments = condition.Pattern.Modifiers?.ToList() ?? new List<string>(),
SameLineOnly = true
});
expression.Append(" AND ");
expression.Append(clauseNumber);
clauseNumber++;
}
else if (condition.SearchIn.Equals("same-file", StringComparison.InvariantCultureIgnoreCase))
{
clauses.Add(new WithinClause()
{
Data = new List<string>() { condition.Pattern.Pattern },
Label = clauseNumber.ToString(CultureInfo.InvariantCulture),
Invert = condition.NegateFinding,
Arguments = condition.Pattern.Modifiers?.ToList() ?? new List<string>(),
SameFile = true
});
expression.Append(" AND ");
expression.Append(clauseNumber);
clauseNumber++;
}
else if (condition.SearchIn.Equals("only-before", StringComparison.InvariantCultureIgnoreCase))
{
clauses.Add(new WithinClause()
{
Data = new List<string>() { condition.Pattern.Pattern },
Label = clauseNumber.ToString(CultureInfo.InvariantCulture),
Invert = condition.NegateFinding,
Arguments = condition.Pattern.Modifiers?.ToList() ?? new List<string>(),
OnlyBefore = true
});
expression.Append(" AND ");
expression.Append(clauseNumber);
clauseNumber++;
}
else if (condition.SearchIn.Equals("only-after", StringComparison.InvariantCultureIgnoreCase))
{
clauses.Add(new WithinClause()
{
Data = new List<string>() { condition.Pattern.Pattern },
Label = clauseNumber.ToString(CultureInfo.InvariantCulture),
Invert = condition.NegateFinding,
Arguments = condition.Pattern.Modifiers?.ToList() ?? new List<string>(),
OnlyAfter = true
});
expression.Append(" AND ");
expression.Append(clauseNumber);
clauseNumber++;
}
}
}
return new ConvertedOatRule(rule.Id, rule)
{
Clauses = clauses,
Expression = expression.ToString()
};
}