Skip to content

Commit aeb4a11

Browse files
committed
(GH-1336) Add syntax aware folding provider
This is a work-in-progress
1 parent 6c96a2d commit aeb4a11

File tree

3 files changed

+145
-1
lines changed

3 files changed

+145
-1
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"publisher": "ms-vscode",
66
"description": "Develop PowerShell scripts in Visual Studio Code!",
77
"engines": {
8-
"vscode": "^1.19.0"
8+
"vscode": "^1.23.0"
99
},
1010
"license": "SEE LICENSE IN LICENSE.txt",
1111
"homepage": "https://github.com/PowerShell/vscode-powershell/blob/master/README.md",

src/features/Folding.ts

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import * as path from "path";
2+
import * as vscode from "vscode";
3+
import {
4+
DocumentFormattingRequest,
5+
DocumentRangeFormattingParams,
6+
DocumentRangeFormattingRequest,
7+
DocumentSelector,
8+
LanguageClient,
9+
RequestType,
10+
} from "vscode-languageclient";
11+
import { IFeature } from "../feature";
12+
13+
const rangeLimit = 5000;
14+
15+
// https://github.com/Microsoft/vscode/issues/46281
16+
const tm = getCoreNodeModule("vscode-textmate");
17+
/**
18+
* Returns a node module installed with VSCode, or null if it fails.
19+
*/
20+
function getCoreNodeModule(moduleName: string) {
21+
try {
22+
return require(`${vscode.env.appRoot}/node_modules.asar/${moduleName}`);
23+
} catch (err) { }
24+
25+
try {
26+
return require(`${vscode.env.appRoot}/node_modules/${moduleName}`);
27+
} catch (err) { }
28+
29+
return null;
30+
}
31+
32+
interface IExtensionGrammar {
33+
language?: string, scopeName?: string, path?: string, embeddedLanguages?: {[scopeName:string]:string}, injectTo?: string[]
34+
}
35+
36+
interface IExtensionPackage {
37+
contributes?: {
38+
languages?: {id: string, configuration: string }[],
39+
grammars?: IExtensionGrammar[],
40+
}
41+
}
42+
43+
export class FoldingProvider implements vscode.FoldingRangeProvider {
44+
private powershellGrammar;
45+
46+
// constructor(
47+
// ) { }
48+
49+
public async provideFoldingRanges(
50+
document: vscode.TextDocument,
51+
context: vscode.FoldingContext,
52+
token: vscode.CancellationToken,
53+
): Promise<vscode.FoldingRange[]> {
54+
55+
const foldingRanges = [];
56+
57+
console.log(document);
58+
console.log(context);
59+
console.log(token);
60+
61+
const content = document.getText();
62+
63+
let tokens = this.grammar().tokenizeLine(content).tokens;
64+
for (var i = 0; i < tokens.length; i++) {
65+
tokens[i]['value'] = content.substring(tokens[i]['startIndex'], tokens[i]['endIndex']);
66+
tokens[i]['startLine'] = document.positionAt(tokens[i]["startIndex"]).line;
67+
tokens[i]['endLine'] = document.positionAt(tokens[i]["endIndex"]).line;
68+
}
69+
70+
// Just force a fixed folding range to see what happens
71+
foldingRanges.push(new vscode.FoldingRange(1, 3, vscode.FoldingRangeKind.Region));
72+
73+
console.log(tokens);
74+
// const tocProvider = new TableOfContentsProvider(this.engine, document);
75+
// let toc = await tocProvider.getToc();
76+
// if (toc.length > rangeLimit) {
77+
// toc = toc.slice(0, rangeLimit);
78+
// }
79+
80+
// const foldingRanges = toc.map((entry, startIndex) => {
81+
// const start = entry.line;
82+
// let end: number | undefined = undefined;
83+
// for (let i = startIndex + 1; i < toc.length; ++i) {
84+
// if (toc[i].level <= entry.level) {
85+
// end = toc[i].line - 1;
86+
// if (document.lineAt(end).isEmptyOrWhitespace && end >= start + 1) {
87+
// end = end - 1;
88+
// }
89+
// break;
90+
// }
91+
// }
92+
// return new vscode.FoldingRange(
93+
// start,
94+
// typeof end === 'number' ? end : document.lineCount - 1);
95+
// });
96+
return foldingRanges;
97+
}
98+
99+
private powerShellGrammarPath(): string {
100+
// "c:\Program Files\Microsoft VS Code\resources\app\extensions\powershell\syntaxes\powershell.tmLanguage.json"
101+
try {
102+
const psGrammars =
103+
vscode.extensions.all
104+
.filter( (x) => x.packageJSON && x.packageJSON.contributes && x.packageJSON.contributes.grammars)
105+
.reduce((a: (IExtensionGrammar&{extensionPath: string})[], b) =>
106+
[...a, ...(b.packageJSON as IExtensionPackage).contributes.grammars
107+
.map( (x) => Object.assign({extensionPath: b.extensionPath}, x))], [])
108+
.filter( (x) => x.language === "powershell");
109+
if (psGrammars.length === 0) { return ""; }
110+
return path.join(psGrammars[0].extensionPath, psGrammars[0].path);
111+
} catch (err) { return ""; }
112+
}
113+
114+
private grammar() {
115+
if (this.powershellGrammar !== undefined) { return this.powershellGrammar; }
116+
const registry = new tm.Registry();
117+
this.powershellGrammar = registry.loadGrammarFromPathSync(this.powerShellGrammarPath());
118+
return this.powershellGrammar;
119+
}
120+
121+
}
122+
123+
export class FoldingFeature implements IFeature {
124+
private foldingProvider: FoldingProvider;
125+
private languageClient: LanguageClient;
126+
127+
constructor(documentSelector: DocumentSelector) {
128+
this.foldingProvider = new FoldingProvider();
129+
vscode.languages.registerFoldingRangeProvider(
130+
documentSelector,
131+
this.foldingProvider);
132+
}
133+
134+
public dispose(): any {
135+
// Should be empty
136+
}
137+
138+
public setLanguageClient(languageclient: LanguageClient): void {
139+
this.languageClient = languageclient;
140+
// this.foldingProvider.setLanguageClient(languageclient);
141+
}
142+
}

src/main.ts

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { DocumentFormatterFeature } from "./features/DocumentFormatter";
1818
import { ExamplesFeature } from "./features/Examples";
1919
import { ExpandAliasFeature } from "./features/ExpandAlias";
2020
import { ExtensionCommandsFeature } from "./features/ExtensionCommands";
21+
import { FoldingFeature } from "./features/Folding";
2122
import { GenerateBugReportFeature } from "./features/GenerateBugReport";
2223
import { HelpCompletionFeature } from "./features/HelpCompletion";
2324
import { NewFileOrProjectFeature } from "./features/NewFileOrProject";
@@ -132,6 +133,7 @@ export function activate(context: vscode.ExtensionContext): void {
132133
new SpecifyScriptArgsFeature(context),
133134
new HelpCompletionFeature(logger),
134135
new CustomViewsFeature(),
136+
new FoldingFeature(documentSelector),
135137
];
136138

137139
sessionManager.setExtensionFeatures(extensionFeatures);

0 commit comments

Comments
 (0)