vscode-region-manager icon indicating copy to clipboard operation
vscode-region-manager copied to clipboard

Feature Request: Add/Update All Regions

Open sunmorgus opened this issue 6 years ago • 9 comments

One thing I would like to request from the excellent extension... the ability to add/update all regions within a .cs file, similar to how the Visual Studio Codemaid extension does this (see below screenshot). I would be happy to help out coding it!

image

sunmorgus avatar Apr 19 '18 11:04 sunmorgus

@sunmorgus hi,
I haven't heard about codemaid extension, but i will try it out and back you asap.

suadev avatar Apr 19 '18 14:04 suadev

@sunmorgus

I think, we can add a new activation event to implement "Include access level in regions" feature. Do you have any suggest for the name? Maybe we can name it "Create All Auto #regions".

In addition, we can add a new configuration parameter named "createAutoRegionsEvenIfTheyAreEmpty" (default value false)

I don't think the "Remove existing regions" feature is really neccessary.

What do you think?

suadev avatar Apr 20 '18 14:04 suadev

I like the names. "createAutoRegionsEvenIfTheyAreEmpty" with a default of false would definitely be good (I don't think most people would like all the empty regions, lol).

I agree with "Remove existing regions" being unnecessary... You've already got a "remove all" so that covers that.

One thing that may be troublesome... how to handle a .cs having methods, properties, fields, etc. that aren't sorted by their access level? In codemaid, it would sort all of them first, and then insert the regions... is that possible in vscode?

sunmorgus avatar Apr 20 '18 15:04 sunmorgus

You are right, it will be troublesome. Actually, i don't know what vscode extension api gives us. entirely.

Let's make some research for this and discuss here. I hope I can spare some time this weekend.

suadev avatar Apr 20 '18 15:04 suadev

Yeah, I'll be available off and on all weekend, would be happy to help! Did a little bit of digging already, and this may be promising... the below function, when called while having the C# extension installed, returns a list of the symbols in the currently active document:

            const { activeTextEditor } = vscode.window;

            if (activeTextEditor && activeTextEditor.document.uri) {
                let success = await vscode.commands.executeCommand(
                    'vscode.executeDocumentSymbolProvider',
                    activeTextEditor.document.uri
                );

                // Display a message box to the user
                vscode.window.showInformationMessage('Hello World!');
            }

The list contains all sorts of good information about the symbol... image

Unfortunately, it doesn't appear to provide the access level... still looking into that.

sunmorgus avatar Apr 20 '18 20:04 sunmorgus

vscode.executeDocumentSymbolProvider looks cool. Maybe there are some other usefull stuff about symbols. I haven't ask to google it yet 😀

suadev avatar Apr 20 '18 21:04 suadev

Ok, I messed around with the symbol stuff yesterday, and I don't think it's going to help us much, because it doesn't seem to be easy to figure out what the "block of code" is from there.

Then I got to thinking about another extension I have installed called "guides"... that extension adds guide lines to blocks of code in the editor, so I did some searching and found the repo for it... turns out the dev uses a regex to determine block based on the indent level... check it out https://github.com/spywhere/vscode-guides/blob/develop/core/indent-guide.ts

I think we could probably use that somehow to figure out the blocks of code, etc, then use the editor APIs to "edit" the active document... what do you think?

sunmorgus avatar Apr 21 '18 19:04 sunmorgus

So, it's a little junky, and probably could be written a lot cleaner, but it's a start... I combined a little bit of the guides code with the symbol provider stuff, and I can get the individual blocks of code from a document (see below code).

It's still buggy... it's returning some methods twice for some reason (I think we may need to remove all regions before processing maybe?), and it's only working for methods right now, need to add in properties, fields, etc..

            const { activeTextEditor } = vscode.window;

            if (activeTextEditor && activeTextEditor.document.uri) {
                let symbols: Array<SymbolInformation> | undefined = await vscode.commands.executeCommand<Array<SymbolInformation>>(
                    'vscode.executeDocumentSymbolProvider',
                    activeTextEditor.document.uri
                );

                if (symbols && symbols.length > 0) {
                    let filteredSymbols: Array<SymbolInformation>;

                    filteredSymbols = symbols.filter(symbol => {
                        return symbol.kind >= 5 && symbol.kind <= 9;
                    });

                    let tabSize = 4; // need to get the actual tab size from settings
                    let pattern = new RegExp(` {${tabSize}}| {0,${tabSize - 1}}\t`, "g");
                    let blocks: Range[] = [];

                    filteredSymbols.forEach(symbol => {
                        let startLineNumber: number = symbol.location.range.start.line;
                        let endLineNumber: number;

                        let text = activeTextEditor.document.lineAt(startLineNumber).text;
                        let lineMatch = text.match(pattern);

                        if (lineMatch && lineMatch.length > 0) {
                            let lineIndent = lineMatch.length;
                            switch (symbol.kind) {
                                case 5: // method
                                    let nextLineNumber = startLineNumber + 2; // class opening brace should be on the next line, we can check for that later though
                                    let currentText = activeTextEditor.document.lineAt(nextLineNumber).text;
                                    let currentLineMatch = currentText.match(pattern);
                                    if (currentLineMatch && currentLineMatch.length > 0) {
                                        let currentLineIndent = currentLineMatch.length;

                                        while (currentLineIndent > lineIndent) {
                                            nextLineNumber++;
                                            currentText = activeTextEditor.document.lineAt(nextLineNumber).text;
                                            currentLineMatch = currentText.match(pattern);
                                            if (currentLineMatch && currentLineMatch.length > 0) {
                                                currentLineIndent = currentLineMatch.length;
                                            }
                                        }

                                        endLineNumber = nextLineNumber;
                                        let blockRange: Range = new Range(startLineNumber, 0, endLineNumber, currentText.length);
                                        blocks.push(blockRange);
                                    }
                                    break;
                            }
                        }

                        if (blocks.length > 0) {
                            blocks.forEach(block => {
                                let textBlock = activeTextEditor.document.getText(block);
                                console.log(textBlock);
                            });
                        }
                    });
                }
            }

sunmorgus avatar Apr 22 '18 12:04 sunmorgus

@sunmorgus it looks good for starting! I really appreciate your effort.

I am also planning to dive into 'executeDocumentSymbolProvider' api. asap :)

suadev avatar Apr 22 '18 21:04 suadev