Skip to content

(GH-1437) Fix detecting contiguous comment blocks and regions #1438

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 31 additions & 43 deletions src/features/Folding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,22 @@ interface ILineNumberRangeList extends Array<LineNumberRange> { }
export class FoldingProvider implements vscode.FoldingRangeProvider {
private powershellGrammar: IGrammar;

/**
* These regular expressions are used to match lines which mark the start and end of region comment in a PowerShell
* script. They are based on the defaults in the VS Code Language Configuration at;
* https://github.com/Microsoft/vscode/blob/64186b0a26/extensions/powershell/language-configuration.json#L26-L31
*/
private readonly startRegionText = /^\s*#region\b/i;
private readonly endRegionText = /^\s*#endregion\b/i;
/**
* This regular expressions is used to detect a line comment (as opposed to an inline comment), that is not a region
* block directive i.e.
* - No text between the beginning of the line and `#`
* - Comment does start with region
* - Comment does start with endregion
*/
private readonly lineCommentText = /\s*#(?!region\b|endregion\b)/i;

constructor(
powershellGrammar: IGrammar,
) {
Expand Down Expand Up @@ -310,34 +326,16 @@ export class FoldingProvider implements vscode.FoldingRangeProvider {
}

/**
* Given a zero based offset, find the line text preceeding it in the document
* Given a zero based offset, find the line in the document
* @param offset Zero based offset in the document
* @param document The source text document
* @returns The line text preceeding the offset, not including the preceeding Line Feed
* @returns The line at the offset
*/
private preceedingText(
private lineAtOffset(
offset: number,
document: vscode.TextDocument,
): string {
const endPos = document.positionAt(offset);
const startPos = endPos.translate(0, -endPos.character);

return document.getText(new vscode.Range(startPos, endPos));
}

/**
* Given a zero based offset, find the line text after it in the document
* @param offset Zero based offset in the document
* @param document The source text document
* @returns The line text after the offset, not including the subsequent Line Feed
*/
private subsequentText(
offset: number,
document: vscode.TextDocument,
): string {
const startPos: vscode.Position = document.positionAt(offset);
const endPos: vscode.Position = document.lineAt(document.positionAt(offset)).range.end;
return document.getText(new vscode.Range(startPos, endPos));
): vscode.TextLine {
return document.lineAt(document.positionAt(offset));
}

/**
Expand All @@ -353,19 +351,16 @@ export class FoldingProvider implements vscode.FoldingRangeProvider {
document: vscode.TextDocument,
): ILineNumberRangeList {
const result = [];

const emptyLine = /^\s*$/;

let startLine: number = -1;
let nextLine: number = -1;

tokens.forEach((token) => {
if (token.scopes.indexOf("punctuation.definition.comment.powershell") !== -1) {
const line: vscode.TextLine = this.lineAtOffset(token.startIndex, document);
// The punctuation.definition.comment.powershell token matches new-line comments
// and inline comments e.g. `$x = 'foo' # inline comment`. We are only interested
// in comments which begin the line i.e. no preceeding text
if (emptyLine.test(this.preceedingText(token.startIndex, document))) {
const lineNum = document.positionAt(token.startIndex).line;
// and inline comments e.g. `$x = 'foo' # inline comment`.
if (this.lineCommentText.test(line.text)) {
const lineNum = line.lineNumber;
// A simple pattern for keeping track of contiguous numbers in a known sorted array
if (startLine === -1) {
startLine = lineNum;
Expand Down Expand Up @@ -420,21 +415,14 @@ export class FoldingProvider implements vscode.FoldingRangeProvider {
document: vscode.TextDocument,
): ITokenList {
const result = [];

const emptyLine = /^\s*$/;
const startRegionText = /^#region\b/i;
const endRegionText = /^#endregion\b/i;

tokens.forEach((token) => {
if (token.scopes.indexOf("punctuation.definition.comment.powershell") !== -1) {
if (emptyLine.test(this.preceedingText(token.startIndex, document))) {
const commentText = this.subsequentText(token.startIndex, document);
if (startRegionText.test(commentText)) {
result.push(this.addTokenScope(token, "custom.start.region"));
}
if (endRegionText.test(commentText)) {
result.push(this.addTokenScope(token, "custom.end.region"));
}
const line: string = this.lineAtOffset(token.startIndex, document).text;
if (this.startRegionText.test(line)) {
result.push(this.addTokenScope(token, "custom.start.region"));
}
if (this.endRegionText.test(line)) {
result.push(this.addTokenScope(token, "custom.end.region"));
}
}
});
Expand Down
3 changes: 3 additions & 0 deletions test/features/folding.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ suite("Features", () => {
{ start: 41, end: 45, kind: 3 },
{ start: 51, end: 53, kind: 3 },
{ start: 56, end: 59, kind: 3 },
{ start: 64, end: 66, kind: 1 },
{ start: 67, end: 72, kind: 3 },
{ start: 68, end: 70, kind: 1 },
];

test("Can detect all of the foldable regions in a document with CRLF line endings", async () => {
Expand Down
12 changes: 12 additions & 0 deletions test/fixtures/folding-crlf.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,15 @@ double quoted herestrings should also fold
'should fold2'
)
}

# Make sure contiguous comment blocks can be folded properly

# Comment Block 1
# Comment Block 1
# Comment Block 1
#region Comment Block 3
# Comment Block 2
# Comment Block 2
# Comment Block 2
$something = $true
#endregion Comment Block 3
12 changes: 12 additions & 0 deletions test/fixtures/folding-lf.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,15 @@ double quoted herestrings should also fold
'should fold2'
)
}

# Make sure contiguous comment blocks can be folded properly

# Comment Block 1
# Comment Block 1
# Comment Block 1
#region Comment Block 3
# Comment Block 2
# Comment Block 2
# Comment Block 2
$something = $true
#endregion Comment Block 3