Skip to content

Commit de00cf3

Browse files
rkeithhillglennsarti
authored andcommitted
(PowerShellGH-1413) Update grammar parsing for vscode-textmate v4 module
VS Code 1.25 has updated the imported vsode-textmate module from v3 to v4, which introduced some breaking changes. This commit updates the grammar loader; * Uses a thenable grammar parser, as V4 of the module is all asynchronous * Uses a simple method detection technique on the Registry object to determine if we're using v3 or v4+ of the textmate module, and then branch the code accordingly. Note that this functionality can only be tested manually due to how the vscode-textmate module is incorporated into VSCode and the test-suite.
1 parent 4619210 commit de00cf3

File tree

2 files changed

+33
-22
lines changed

2 files changed

+33
-22
lines changed

src/features/Folding.ts

+31-20
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
/*---------------------------------------------------------
22
* Copyright (C) Microsoft Corporation. All rights reserved.
33
*--------------------------------------------------------*/
4-
4+
import fs = require("fs");
55
import * as path from "path";
66
import * as vscode from "vscode";
77
import {
88
DocumentSelector,
99
LanguageClient,
1010
} from "vscode-languageclient";
1111
import { IFeature } from "../feature";
12-
import { Logger } from "../logging";
12+
import { ILogger } from "../logging";
1313
import * as Settings from "../settings";
1414

1515
/**
@@ -497,23 +497,26 @@ export class FoldingFeature implements IFeature {
497497
* @param logger The logging object to send messages to
498498
* @param documentSelector documentSelector object for this Folding Provider
499499
*/
500-
constructor(private logger: Logger, documentSelector: DocumentSelector) {
501-
const grammar: IGrammar = this.grammar(logger);
502-
500+
constructor(private logger: ILogger, documentSelector: DocumentSelector) {
503501
const settings = Settings.load();
504502
if (!(settings.codeFolding && settings.codeFolding.enable)) { return; }
505503

506-
// If the PowerShell grammar is not available for some reason, don't register a folding provider,
507-
// which reverts VSCode to the default indentation style folding
508-
if (grammar == null) {
509-
logger.writeWarning("Unable to load the PowerShell grammar file");
510-
return;
511-
}
504+
this.loadPSGrammar(logger)
505+
.then((grammar) => {
506+
// If the PowerShell grammar is not available for some reason, don't register a folding provider,
507+
// which reverts VSCode to the default indentation style folding
508+
if (!grammar) {
509+
logger.writeWarning("Unable to load the PowerShell grammar file");
510+
return;
511+
}
512512

513-
this.foldingProvider = new FoldingProvider(grammar);
514-
vscode.languages.registerFoldingRangeProvider(documentSelector, this.foldingProvider);
513+
this.foldingProvider = new FoldingProvider(grammar);
514+
vscode.languages.registerFoldingRangeProvider(documentSelector, this.foldingProvider);
515515

516-
logger.write("Syntax Folding Provider registered");
516+
logger.write("Syntax Folding Provider registered");
517+
}, (err) => {
518+
this.logger.writeError(`Failed to load grammar file - error: ${err}`);
519+
});
517520
}
518521

519522
/* dispose() is required by the IFeature interface, but is not required by this feature */
@@ -527,7 +530,7 @@ export class FoldingFeature implements IFeature {
527530
* @param logger The logging object to send messages to
528531
* @returns A grammar parser for the PowerShell language is succesful or undefined if an error occured
529532
*/
530-
public grammar(logger: Logger): IGrammar {
533+
public loadPSGrammar(logger: ILogger): Thenable<IGrammar> {
531534
const tm = this.getCoreNodeModule("vscode-textmate", logger);
532535
if (tm == null) { return undefined; }
533536
logger.writeDiagnostic(`Loaded the vscode-textmate module`);
@@ -537,10 +540,18 @@ export class FoldingFeature implements IFeature {
537540
const grammarPath = this.powerShellGrammarPath();
538541
if (grammarPath == null) { return undefined; }
539542
logger.writeDiagnostic(`PowerShell grammar file specified as ${grammarPath}`);
540-
try {
541-
return registry.loadGrammarFromPathSync(grammarPath);
542-
} catch (err) {
543-
logger.writeError(`Error while loading the PowerShell grammar file at ${grammarPath}`, err);
543+
544+
// Branching for the different vscode-textmate modules
545+
if ("loadGrammarFromPathSync" in registry) {
546+
// V3 of the module allows synchronous loading of a grammar
547+
return new Promise( (grammar) => {
548+
return registry.loadGrammarFromPathSync(grammarPath);
549+
});
550+
} else {
551+
// However in V4+ this is async only
552+
const content = fs.readFileSync(grammarPath);
553+
const rawGrammar = tm.parseRawGrammar(content.toString(), grammarPath);
554+
return registry.addGrammar(rawGrammar);
544555
}
545556
}
546557

@@ -552,7 +563,7 @@ export class FoldingFeature implements IFeature {
552563
* @param logger The logging object to send messages to
553564
* @returns The required module, or null if the module cannot be required
554565
*/
555-
private getCoreNodeModule(moduleName: string, logger: Logger) {
566+
private getCoreNodeModule(moduleName: string, logger: ILogger) {
556567
// Attempt to load the module from known locations
557568
const loadLocations: string[] = [
558569
`${vscode.env.appRoot}/node_modules.asar/${moduleName}`,

test/features/folding.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ function assertFoldingRegions(result, expected): void {
2424

2525
suite("Features", () => {
2626

27-
suite("Folding Provider", () => {
27+
suite("Folding Provider", async () => {
2828
const logger: MockLogger = new MockLogger();
2929
const mockSelector: DocumentSelector = [
3030
{ language: "powershell", scheme: "file" },
3131
];
32-
const psGrammar = (new folding.FoldingFeature(logger, mockSelector)).grammar(logger);
32+
const psGrammar = await (new folding.FoldingFeature(logger, mockSelector)).loadPSGrammar(logger);
3333
const provider = (new folding.FoldingProvider(psGrammar));
3434

3535
test("Can detect the PowerShell Grammar", () => {

0 commit comments

Comments
 (0)