Skip to content
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

Add option to show last line with syntax-aware code folding #1546

Closed
wants to merge 4 commits into from

Conversation

RussPitcher
Copy link

@RussPitcher RussPitcher commented Sep 26, 2018

PR Summary

Add a settings option to enable the last line of a syntax-aware folded section to be displayed when the section is folded. Relates to issue #1514

I have added a speculative note in the changelog.md file as I wasn't sure if I should update it or not.

PR Checklist

Note: Tick the boxes below that apply to this pull request by putting an x between the square brackets.
Please mark anything not applicable to this PR NA.

  • PR has a meaningful title
  • Summarized changes
  • This PR is ready to merge and is not work in progress
    • If the PR is work in progress, please add the prefix WIP: to the beginning of the title and remove the prefix when the PR is ready

@msftclas
Copy link

msftclas commented Sep 26, 2018

CLA assistant check
All CLA requirements met.

@rjmholt
Copy link
Contributor

rjmholt commented Sep 27, 2018

Tagging @glennsarti for review (won't let me add you in the reviewers dropdown...)

@rjmholt
Copy link
Contributor

rjmholt commented Sep 27, 2018

@RussPitcher No need to add to the changelog -- even though I would like it to be done in each PR, it would create merge conflicts for every PR. So we generate it at release time. Just make sure you include a pithy description in your commit messages (which we squash, but will do our best to preserve information from).

Copy link
Contributor

@rjmholt rjmholt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've cloned and tested this branch (it might be easier in future to choose a non-master branch, since the mechanism for checking out a GitHub PR branch only works if that branch's name doesn't conflict with an existing one).

Looks like it works really nicely -- a really great addition. Thanks so much for contributing this @RussPitcher.

I'll let you revert the changelog addition. The other thing that might be worth adding is a couple of tests, since @glennsarti went to some effort to write tests for the folding code.

I'll let @tylerl0706, @rkeithhill and @glennsarti review as well before we do anything.

@@ -1,5 +1,8 @@
# vscode-powershell Release History

- [vscode-PowerShell #????](https://github.com/PowerShell/vscode-PowerShell/pull/????) -
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will cause merge conflicts later on if we leave it in. If you put your summary from here into a commit message, it will make its way into the changelog.

Just stick the summary into a commit taking out the changelog entry is probably the easiest way to go. Otherwise there is also the git commit --amend -> git push origin +branch option.

@@ -478,6 +478,11 @@
"default": true,
"description": "Enables syntax based code folding. When disabled, the default indentation based code folding is used."
},
"powershell.codeFolding.showLastLine": {
"type": "boolean",
"default": false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tylerl0706 @rkeithhill @glennsarti @RussPitcher Thoughts on this being the default? (Note as in the description below that this is VSCode's default)

constructor(
rangeKind: vscode.FoldingRangeKind,
) {
this.rangeKind = rangeKind;
this.settings = Settings.load();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to ensure that settings are only loaded once? Like passing them into the constructor? Or does Settings.load() guarantee that (I assume it does actually, but want to check)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1. Settings should go into the constructor signature.

Settings.load() has no side effects (that I know of) but in theory there could be some race conditions?

@@ -121,6 +124,9 @@ class LineNumberRange {
): LineNumberRange {
this.startline = document.positionAt(start.startIndex).line;
this.endline = document.positionAt(end.startIndex).line;
if (this.settings.codeFolding && this.settings.codeFolding.showLastLine) {
this.endline--;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume endline-1 is never going to be a bad value for VSCode. We might want to test some edge cases here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a guard here to make sure that endline is never less than startline

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acutally, in retrospect. This is wrong place to do this. Because, changing the endline too early means the isValidRange function will give out false positives (

return (this.endline - this.startline >= 1);
)

Instead it should replace

public toFoldingRange(): vscode.FoldingRange {
return new vscode.FoldingRange(this.startline, this.endline, this.rangeKind);
}

    public toFoldingRange(settings:ISettings): vscode.FoldingRange {
        if (settings.codeFolding && settings.codeFolding.showLastLine) {
            return new vscode.FoldingRange(this.startline, this.endline - 1, this.rangeKind);
        } else {
            return new vscode.FoldingRange(this.startline, this.endline, this.rangeKind);
        }
    }

And then change the provideFoldingRanges method to;

return foldableRegions
// It's possible to have duplicate or overlapping ranges, that is, regions which have the same starting
// line number as the previous region. Therefore only emit ranges which have a different starting line
// than the previous range.
.filter((item, index, src) => index === 0 || item.startline !== src[index - 1].startline)
// Convert the internal representation into the VSCode expected type
.map((item) => item.toFoldingRange());

        const settings = this.currentSettings();
        return foldableRegions
            // It's possible to have duplicate or overlapping ranges, that is, regions which have the same starting
            // line number as the previous region. Therefore only emit ranges which have a different starting line
            // than the previous range.
            .filter((item, index, src) => index === 0 || item.startline !== src[index - 1].startline)
            // Convert the internal representation into the VSCode expected type
            .map((item) => item.toFoldingRange(settings));
    }

    private currentSettings(): ISettings { Settings.load(); }

The private method currentSettings() is needed so we can mock it in the unit tests to flick the behaviour.

Copy link
Contributor

@glennsarti glennsarti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Requires some changes to setting detection
  • +1 to making this the default. However this will change the setting detection
  • This really requires test changes if we make it the default, all of the tests will break.

@@ -121,6 +124,9 @@ class LineNumberRange {
): LineNumberRange {
this.startline = document.positionAt(start.startIndex).line;
this.endline = document.positionAt(end.startIndex).line;
if (this.settings.codeFolding && this.settings.codeFolding.showLastLine) {
this.endline--;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a guard here to make sure that endline is never less than startline

constructor(
rangeKind: vscode.FoldingRangeKind,
) {
this.rangeKind = rangeKind;
this.settings = Settings.load();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1. Settings should go into the constructor signature.

Settings.load() has no side effects (that I know of) but in theory there could be some race conditions?

@glennsarti
Copy link
Contributor

@rjmholt @RussPitcher I've raised an alternate implementation of this PR at #1551. I've kept the commit messages horrible but if we choose to use that they can be cleaned up.

@TylerLeonhardt
Copy link
Member

Closing this in favor of #1557 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants