diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..03b780591 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "files.exclude": { + "rascal-lsp": true, + "rascal-vscode-extension": true + } +} \ No newline at end of file diff --git a/rascal-language-servers.code-workspace b/rascal-language-servers.code-workspace index 3d6ee5fae..7b0aa5747 100644 --- a/rascal-language-servers.code-workspace +++ b/rascal-language-servers.code-workspace @@ -5,6 +5,10 @@ }, { "path": "rascal-vscode-extension" + }, + { + "name": "root", + "path": "." } ], "extensions": { diff --git a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java index e07f22e06..872fea6f9 100644 --- a/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java +++ b/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/parametric/ParametricTextDocumentService.java @@ -644,7 +644,17 @@ private static T last(List l) { } private Optional safeLanguage(ISourceLocation loc) { - return Optional.ofNullable(registeredExtensions.get(extension(loc))); + var ext = extension(loc); + if ("".equals(ext)) { + if (contributions.size() == 1) { + logger.trace("file was opened without an extension; falling back to the single registered language for: {}", loc); + return contributions.keySet().stream().findFirst(); + } else { + logger.error("file was opened without an extension and there are multiple languages registered, so we cannot pick a fallback for: {}", loc); + return Optional.empty(); + } + } + return Optional.ofNullable(registeredExtensions.get(ext)); } private String language(ISourceLocation loc) { diff --git a/rascal-vscode-extension/src/test/vscode-suite/dsl.test.ts b/rascal-vscode-extension/src/test/vscode-suite/dsl.test.ts index 1963d5bbf..936f9a43b 100644 --- a/rascal-vscode-extension/src/test/vscode-suite/dsl.test.ts +++ b/rascal-vscode-extension/src/test/vscode-suite/dsl.test.ts @@ -25,7 +25,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -import { SideBarView, VSBrowser, WebDriver, Workbench } from 'vscode-extension-tester'; +import { InputBox, TextEditor, SideBarView, VSBrowser, WebDriver, Workbench } from 'vscode-extension-tester'; import { Delays, IDEOperations, ignoreFails, printRascalOutputOnFailure, RascalREPL, sleep, TestWorkspace } from './utils'; import { expect } from 'chai'; @@ -75,7 +75,6 @@ parameterizedDescribe(function (errorRecovery: boolean) { await repl.terminate(); } - before(async () => { browser = VSBrowser.instance; driver = browser.driver; @@ -103,7 +102,7 @@ parameterizedDescribe(function (errorRecovery: boolean) { await fs.writeFile(TestWorkspace.picoFile, picoFileBackup); }); - it("have highlighting and parse errors", async function () { + it("has highlighting and parse errors", async function () { await ignoreFails(new Workbench().getEditorView().closeAllEditors()); const editor = await ide.openModule(TestWorkspace.picoFile); const isPicoLoading = ide.statusContains("Pico"); @@ -126,7 +125,7 @@ parameterizedDescribe(function (errorRecovery: boolean) { } }).retries(2); - it("have highlighting and parse errors for second extension", async function () { + it("has highlighting and parse errors for second extension", async function () { const editor = await ide.openModule(TestWorkspace.picoNewFile); await ide.hasSyntaxHighlighting(editor); try { @@ -137,6 +136,40 @@ parameterizedDescribe(function (errorRecovery: boolean) { } }); + it("has syntax highlighting in documents without extension", async function () { + await bench.executeCommand("workbench.action.files.newUntitledFile"); + await bench.executeCommand("workbench.action.editor.changeLanguageMode"); + + const inputBox = new InputBox(); + await inputBox.setText("parametric-rascalmpl"); + await inputBox.confirm(); + + const file = "Untitled-1"; + const editor = await driver.wait(async () => { + const result = await ignoreFails(new Workbench().getEditorView().openEditor(file)) as TextEditor; + if (result && await ignoreFails(result.getTitle()) === file) { + return result; + } + return undefined! as TextEditor; + }, Delays.normal, "Could not open file"); + expect(editor).to.not.be.undefined; + + await editor.setText(`begin + declare + a : natural; + a := 2 +end +`); + await ide.hasSyntaxHighlighting(editor, Delays.slow); + + try { + await editor.setTextAtLine(4, " a := "); + await ide.hasErrorSquiggly(editor, Delays.slow); + } finally { + await ide.revertOpenChanges(); + } + }).retries(2); + it("error recovery works", async function () { if (!errorRecovery) { this.skip(); } const editor = await ide.openModule(TestWorkspace.picoNewFile);