in DevSkim-VSCode-Plugin/server/src/utility_classes/suppressions.ts [99:249]
private addAction(ruleID: string, documentContents: string, startCharacter: number, lineStart: number,
langID: string, isReviewRule: boolean, daysOffset: number = -1): DevSkimAutoFixEdit
{
let action: DevSkimAutoFixEdit = Object.create(null);
let regex: RegExp = (isReviewRule)
? DevSkimSuppression.reviewRegEx
: DevSkimSuppression.suppressionRegEx;
let startingWhitespace = " ";
this.setActionFixName(isReviewRule, action, ruleID, daysOffset);
//make the day in the future that a time based expression will expire
const date = new Date();
if (!isReviewRule && daysOffset > 0)
{
date.setDate(date.getDate() + daysOffset);
}
//find the end of the current line of the finding
let XRegExp = require('xregexp');
let range: Range;
let match;
//start off generating a new suppression. If its going on the same line as the finding look for the
//newline (if it exists) and insert just before it
if(this.dsSettings.suppressionCommentPlacement == "same line as finding")
{
//check to see if this is the end of the document or not, as there is no newline at the end
match = XRegExp.exec(documentContents, DocumentUtilities.newlinePattern, startCharacter);
if (match)
{
let columnStart = (lineStart == 0)
? match.index
: match.index - documentContents.substr(0, match.index).lastIndexOf("\n") - 1;
range = Range.create(lineStart, columnStart, lineStart, columnStart + match[0].length);
documentContents = documentContents.substr(0, match.index);
}
else
{
//replace with end of file
let columnStart = (lineStart == 0)
? documentContents.length
: documentContents.length - documentContents.lastIndexOf("\n") - 1;
range = Range.create(lineStart, columnStart, lineStart, columnStart);
}
}
//if the suppression goes on the line above the logic is much simpler - we just insert at the front
//of the line and below we add a newline at the end of the suppression
else
{
range = Range.create(lineStart, 0, lineStart, 0);
startingWhitespace = DocumentUtilities.GetLeadingWhiteSpace(documentContents, lineStart);
}
// if there is an existing suppression that has expired (or there for a different issue)
// then it needs to be replaced
let existingSuppression : DevSkimSuppressionFinding;
let suppressionStart : number = startCharacter;
let suppressionLine : number = lineStart;
//this checks for any existing suppression, regardless of whether it is expired, or for a different finding, because regardless
//that comment gets modified
existingSuppression= DevSkimSuppression.isFindingCommented(startCharacter,documentContents,ruleID,langID, isReviewRule, true);
//yep, there is an existing suppression, so start working off of its location
if (existingSuppression.showSuppressionFinding)
{
suppressionStart = DocumentUtilities.GetDocumentPosition(documentContents, existingSuppression.suppressionRange.start.line);
suppressionLine = existingSuppression.suppressionRange.start.line;
}
//now get the actual suppression text out so it can be modified
match = XRegExp.exec(documentContents, regex, suppressionStart);
if (match && DocumentUtilities.GetLineNumber(documentContents, match.index) == suppressionLine)
{
//parse the existing suppression and set the range/text to modify it
let columnStart: number = (suppressionLine == 0) ? match.index : match.index - documentContents.substr(0, match.index).lastIndexOf("\n") - 1;
range = Range.create(suppressionLine, columnStart, suppressionLine, columnStart + match[0].length);
if (match[1] !== undefined && match[1] != null && match[1].length > 0)
{
//the existing ruleID was found, so just set it to that string (may include other rules too)
//this would be an instance where the date has expired
if (match[1].indexOf(ruleID) >= 0)
{
ruleID = match[1];
}
//the finding rule id wasn't found, so this is an instance where there is a separate finding suppressed
//on the same line. Append
else
{
ruleID = ruleID + "," + match[1];
}
}
if (isReviewRule || daysOffset > 0)
{
action.text = this.makeActionString(ruleID, isReviewRule, date);
}
else
{
action.text = this.makeActionString(ruleID, isReviewRule);
}
}
// if there is not an existing suppression we need to create the full suppression text
else
{
let StartComment: string = "";
let EndComment : string = "";
//select the right comment type, based on the user settings and the
//comment capability of the programming language
if(this.dsSettings.suppressionCommentStyle == "block")
{
StartComment = SourceContext.GetBlockCommentStart(langID);
EndComment = SourceContext.GetBlockCommentEnd(langID);
if (!StartComment || StartComment.length < 1 || !EndComment || EndComment.length < 1)
{
StartComment = SourceContext.GetLineComment(langID);
}
}
else
{
StartComment = SourceContext.GetLineComment(langID);
if (!StartComment || StartComment.length < 1)
{
StartComment = SourceContext.GetBlockCommentStart(langID);
EndComment = SourceContext.GetBlockCommentEnd(langID);
}
}
let optionalNewline: string = "";
//we will need a newline if this suppression is supposed to go above the finding
if (this.dsSettings.suppressionCommentPlacement == "line above finding")
{
optionalNewline = DocumentUtilities.GetNewlineCharacter(documentContents);
}
//make the actual text inserted as the suppression
if (isReviewRule || daysOffset > 0)
{
action.text = startingWhitespace + StartComment + this.makeActionString(ruleID, isReviewRule, date) + " " + EndComment + optionalNewline;
}
else
{
action.text = startingWhitespace + StartComment + this.makeActionString(ruleID, isReviewRule) + " " + EndComment + optionalNewline;
}
}
action.range = range;
return action;
}