|
| 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 | +} |
0 commit comments