in DevSkim-VSCode-Plugin/server/src/devskimWorker.ts [305:404]
private runAnalysis(documentContents: string, langID: string, documentURI: string, includeSuppressions : boolean = true): DevSkimProblem[]
{
let problems: DevSkimProblem[] = [];
let XRegExp = require('xregexp');
//iterate over all of the rules, and then all of the patterns within a rule looking for a match.
for (let rule of this.analysisRules)
{
const ruleSeverity: DevskimRuleSeverity = DevSkimWorker.MapRuleSeverity(rule.severity);
//if the rule doesn't apply to whatever language we are analyzing (C++, Java, etc.) or we aren't processing
//that particular severity skip the rest
if (this.dswSettings.getSettings().ignoreRulesList.indexOf(rule.id) == -1 && /*check to see if this is a rule the user asked to ignore */
DevSkimWorker.appliesToLangOrFile(langID, rule.applies_to, rule.does_not_apply_to, documentURI) &&
this.RuleSeverityEnabled(ruleSeverity))
{
for (let patternIndex = 0; patternIndex < rule.patterns.length; patternIndex++)
{
let modifiers: string[] = (rule.patterns[patternIndex].modifiers != undefined && rule.patterns[patternIndex].modifiers.length > 0) ?
rule.patterns[patternIndex].modifiers.concat(["g"]) : ["g"];
const matchPattern: RegExp = DevSkimWorker.MakeRegex(rule.patterns[patternIndex].type, rule.patterns[patternIndex].pattern, modifiers, true);
//go through all of the text looking for a match with the given pattern
let matchPosition = 0;
let match = XRegExp.exec(documentContents, matchPattern, matchPosition);
while (match)
{
//if the rule doesn't contain any conditions, set it to an empty array to make logic later easier
if (!rule.conditions)
{
rule.conditions = [];
}
//check to see if this finding has either been suppressed or reviewed (for manual-review rules)
//the suppressionFinding object contains a flag if the finding has been suppressed as well as
//range info for the ruleID in the suppression text so that hover text can be added describing
//the finding that was suppress
let suppressionFinding: DevSkimSuppressionFinding = DevSkimSuppression.isFindingCommented(match.index, documentContents, rule.id,langID, (ruleSeverity == DevskimRuleSeverity.ManualReview));
//calculate what line we are on by grabbing the text before the match & counting the newlines in it
let lineStart: number = DocumentUtilities.GetLineNumber(documentContents, match.index);
let newlineIndex: number = (lineStart == 0) ? -1 : documentContents.substr(0, match.index).lastIndexOf("\n");
let columnStart: number = match.index - newlineIndex - 1;
//since a match may span lines (someone who broke a long function invocation into multiple lines for example)
//it's necessary to see if there are any newlines WITHIN the match so that we get the line the match ends on,
//not just the line it starts on. Also, we use the substring for the match later when making fixes
let replacementSource: string = documentContents.substr(match.index, match[0].length);
let lineEnd: number = DocumentUtilities.GetLineNumber(replacementSource, replacementSource.length) + lineStart;
let columnEnd = (lineStart == lineEnd) ?
columnStart + match[0].length :
match[0].length - documentContents.substr(match.index).indexOf("\n") - 1;
let range: Range = Range.create(lineStart, columnStart, lineEnd, columnEnd);
// Is this *not* a suppression finding (a real issue)
if (!suppressionFinding.showSuppressionFinding)
{
if (DocumentUtilities.MatchIsInScope(langID, documentContents.substr(0, match.index), newlineIndex, rule.patterns[patternIndex].scopes))
{
if (DevSkimWorker.MatchesConditions(rule.conditions, documentContents, range, langID))
{
let snippet = [];
for (let i=Math.max(0, lineStart - 2); i<=lineEnd + 2; i++)
{
const snippetLine = DocumentUtilities.GetLine(documentContents, i);
snippet.push(snippetLine.substr(0, 80));
}
//add in any fixes
let problem: DevSkimProblem = this.MakeProblem(rule, DevSkimWorker.MapRuleSeverity(rule.severity), range, snippet.join('\n'));
problem.fixes = problem.fixes.concat(DevSkimWorker.MakeFixes(rule, replacementSource, range));
problem.fixes = problem.fixes.concat(this.dsSuppressions.createActions(rule.id, documentContents, match.index, lineStart, langID, ruleSeverity));
problem.filePath = documentURI;
problems.push(problem);
}
}
}
//throw a pop up if there is a review/suppression comment with the rule id, so that people can figure out what was
//suppressed/reviewed
else {
if (!suppressionFinding.noRange && includeSuppressions && this.RuleSeverityEnabled(DevskimRuleSeverity.WarningInfo))
{
//highlight suppression finding for context
//this will look
let problem: DevSkimProblem = this.MakeProblem(rule, DevskimRuleSeverity.WarningInfo, suppressionFinding.suppressionRange,"", range);
problems.push(problem);
}
}
//advance the location we are searching in the line
matchPosition = match.index + match[0].length;
match = XRegExp.exec(documentContents, matchPattern, matchPosition);
}
}
}
}
return problems;
}