From 4c31d97461bd212085b1f5339dbb61e04d13b531 Mon Sep 17 00:00:00 2001 From: Lionel Henry Date: Tue, 26 Mar 2024 11:33:17 +0100 Subject: [PATCH 1/7] Set up indent testing for R extension --- .../positron-r/src/test/editor-utils.ts | 93 +++++++++++++++++++ .../positron-r/src/test/indentation.test.ts | 11 +++ 2 files changed, 104 insertions(+) create mode 100644 extensions/positron-r/src/test/editor-utils.ts create mode 100644 extensions/positron-r/src/test/indentation.test.ts diff --git a/extensions/positron-r/src/test/editor-utils.ts b/extensions/positron-r/src/test/editor-utils.ts new file mode 100644 index 00000000000..32d68e52039 --- /dev/null +++ b/extensions/positron-r/src/test/editor-utils.ts @@ -0,0 +1,93 @@ +// From testUtils.ts in the typescript-language-feature extension +// https://github.com/posit-dev/positron/blob/main/extensions/typescript-language-features/src/test/testUtils.ts + +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import * as fs from 'fs'; +import * as os from 'os'; +import { join } from 'path'; +import * as vscode from 'vscode'; + +export function rndName() { + let name = ''; + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + for (let i = 0; i < 10; i++) { + name += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return name; +} + +export function createRandomFile(contents = '', fileExtension = 'txt'): Thenable { + return new Promise((resolve, reject) => { + const tmpFile = join(os.tmpdir(), rndName() + '.' + fileExtension); + fs.writeFile(tmpFile, contents, (error) => { + if (error) { + return reject(error); + } + + resolve(vscode.Uri.file(tmpFile)); + }); + }); +} + +export function deleteFile(file: vscode.Uri): Thenable { + return new Promise((resolve, reject) => { + fs.unlink(file.fsPath, (err) => { + if (err) { + reject(err); + } else { + resolve(true); + } + }); + }); +} export const CURSOR = '$$CURSOR$$'; + +export function withRandomFileEditor( + contents: string, + fileExtension: string, + run: (editor: vscode.TextEditor, doc: vscode.TextDocument) => Thenable +): Thenable { + const cursorIndex = contents.indexOf(CURSOR); + return createRandomFile(contents.replace(CURSOR, ''), fileExtension).then(file => { + return vscode.workspace.openTextDocument(file).then(doc => { + return vscode.window.showTextDocument(doc).then((editor) => { + if (cursorIndex >= 0) { + const pos = doc.positionAt(cursorIndex); + editor.selection = new vscode.Selection(pos, pos); + } + return run(editor, doc).then(_ => { + if (doc.isDirty) { + return doc.save().then(() => { + return deleteFile(file); + }); + } else { + return deleteFile(file); + } + }); + }); + }); + }); +} + +const onDocumentChange = (doc: vscode.TextDocument): Promise => { + return new Promise(resolve => { + const sub = vscode.workspace.onDidChangeTextDocument(e => { + if (e.document !== doc) { + return; + } + sub.dispose(); + resolve(e.document); + }); + }); +}; + +export const type = async (document: vscode.TextDocument, text: string): Promise => { + const onChange = onDocumentChange(document); + await vscode.commands.executeCommand('type', { text }); + await onChange; + return document; +}; diff --git a/extensions/positron-r/src/test/indentation.test.ts b/extensions/positron-r/src/test/indentation.test.ts new file mode 100644 index 00000000000..cb855047358 --- /dev/null +++ b/extensions/positron-r/src/test/indentation.test.ts @@ -0,0 +1,11 @@ +import * as assert from 'assert'; +import { withRandomFileEditor, CURSOR, type } from './editor-utils'; + +suite('Indentation', () => { + test('test', async () => { + return withRandomFileEditor(`1 +${CURSOR}`, 'R', async (_editor, document) => { + await type(document, '\n2'); + assert.strictEqual(document.getText(), '1 +\n 2'); + }); + }); +}); From ca7941dc0b91f5dcf57d9f2d114a2ec720f7a2b7 Mon Sep 17 00:00:00 2001 From: Lionel Henry Date: Fri, 29 Mar 2024 17:43:30 +0100 Subject: [PATCH 2/7] Document how to run tests --- extensions/positron-r/src/test/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 extensions/positron-r/src/test/README.md diff --git a/extensions/positron-r/src/test/README.md b/extensions/positron-r/src/test/README.md new file mode 100644 index 00000000000..dbc281f387b --- /dev/null +++ b/extensions/positron-r/src/test/README.md @@ -0,0 +1,5 @@ +Launch tests by running this from the repository root: + +```sh +yarn test-extension -l positron-r +``` From c3ff622ec83a902dbae42706df6efca7a27a066c Mon Sep 17 00:00:00 2001 From: Lionel Henry Date: Thu, 28 Mar 2024 13:36:53 +0100 Subject: [PATCH 3/7] Add snapshot tests for indentation --- .../positron-r/src/test/editor-utils.ts | 53 +++++------ .../positron-r/src/test/indentation.test.ts | 63 +++++++++++-- .../src/test/snapshots/.vscode/settings.json | 3 + .../src/test/snapshots/indentation-cases.R | 82 +++++++++++++++++ .../test/snapshots/indentation-snapshots.R | 88 +++++++++++++++++++ 5 files changed, 258 insertions(+), 31 deletions(-) create mode 100644 extensions/positron-r/src/test/snapshots/.vscode/settings.json create mode 100644 extensions/positron-r/src/test/snapshots/indentation-cases.R create mode 100644 extensions/positron-r/src/test/snapshots/indentation-snapshots.R diff --git a/extensions/positron-r/src/test/editor-utils.ts b/extensions/positron-r/src/test/editor-utils.ts index 32d68e52039..582449e0781 100644 --- a/extensions/positron-r/src/test/editor-utils.ts +++ b/extensions/positron-r/src/test/editor-utils.ts @@ -6,7 +6,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as assert from 'assert'; import * as fs from 'fs'; import * as os from 'os'; import { join } from 'path'; @@ -44,36 +43,40 @@ export function deleteFile(file: vscode.Uri): Thenable { } }); }); -} export const CURSOR = '$$CURSOR$$'; +} + +export const CURSOR = '"<>"'; -export function withRandomFileEditor( +export async function withFileEditor( contents: string, fileExtension: string, - run: (editor: vscode.TextEditor, doc: vscode.TextDocument) => Thenable -): Thenable { + run: (editor: vscode.TextEditor, doc: vscode.TextDocument) => Promise +): Promise { const cursorIndex = contents.indexOf(CURSOR); - return createRandomFile(contents.replace(CURSOR, ''), fileExtension).then(file => { - return vscode.workspace.openTextDocument(file).then(doc => { - return vscode.window.showTextDocument(doc).then((editor) => { - if (cursorIndex >= 0) { - const pos = doc.positionAt(cursorIndex); - editor.selection = new vscode.Selection(pos, pos); - } - return run(editor, doc).then(_ => { - if (doc.isDirty) { - return doc.save().then(() => { - return deleteFile(file); - }); - } else { - return deleteFile(file); - } - }); - }); - }); - }); + const rawContents = contents.replace(CURSOR, ''); + + const file = await createRandomFile(rawContents, fileExtension); + + try { + const doc = await vscode.workspace.openTextDocument(file); + const editor = await vscode.window.showTextDocument(doc); + + if (cursorIndex >= 0) { + const pos = doc.positionAt(cursorIndex); + editor.selection = new vscode.Selection(pos, pos); + } + + await run(editor, doc); + + if (doc.isDirty) { + await doc.save(); + } + } finally { + deleteFile(file); + } } -const onDocumentChange = (doc: vscode.TextDocument): Promise => { +export const onDocumentChange = (doc: vscode.TextDocument): Promise => { return new Promise(resolve => { const sub = vscode.workspace.onDidChangeTextDocument(e => { if (e.document !== doc) { diff --git a/extensions/positron-r/src/test/indentation.test.ts b/extensions/positron-r/src/test/indentation.test.ts index cb855047358..0b103680b90 100644 --- a/extensions/positron-r/src/test/indentation.test.ts +++ b/extensions/positron-r/src/test/indentation.test.ts @@ -1,11 +1,62 @@ +import * as vscode from 'vscode'; import * as assert from 'assert'; -import { withRandomFileEditor, CURSOR, type } from './editor-utils'; +import * as fs from 'fs'; +import { CURSOR, type, withFileEditor } from './editor-utils'; + +const snapshotsFolder = `${__dirname}/../../src/test/snapshots`; +const snippetsPath = `${snapshotsFolder}/indentation-cases.R`; +const snapshotsPath = `${snapshotsFolder}/indentation-snapshots.R`; + +// FIXME: This should normally be run as part of tests setup in `before()` but +// it's somehow not defined +async function init() { + // Open workspace with custom configuration for snapshots. If you need + // custom settings set them there via `config.update()`. + const uri = vscode.Uri.file(snapshotsFolder); + await vscode.commands.executeCommand('vscode.openFolder', uri, false); + const config = vscode.workspace.getConfiguration(); + + // Prevents `ENOENT: no such file or directory` errors caused by us + // deleting temporary editor files befor Code had the opportunity to + // save the user history of these files (see ) + config.update('workbench.localHistory.enabled', false, vscode.ConfigurationTarget.Workspace); +} suite('Indentation', () => { - test('test', async () => { - return withRandomFileEditor(`1 +${CURSOR}`, 'R', async (_editor, document) => { - await type(document, '\n2'); - assert.strictEqual(document.getText(), '1 +\n 2'); - }); + // This regenerates snapshots in place. If the snapshots differ from last + // run, a failure is emitted. You can either commit the new output or discard + // it if that's a bug to fix. + test('Regenerate and check', async () => { + await init(); + const expected = fs.readFileSync(snapshotsPath, 'utf8'); + const current = await regenerateIndentSnapshots(); + + // Update snapshot file + fs.writeFileSync(snapshotsPath, current, 'utf8'); + + // Notify if snapshots were outdated + assert.strictEqual(expected, current); + console.log('dirname: ', __dirname); }); }); + +async function regenerateIndentSnapshots() { + const snippets = fs. + readFileSync(snippetsPath, 'utf8'). + split('# ---\n'); + + // Remove documentation snippet + snippets.splice(0, 1); + + const snapshots: string[] = ['# File generated from `indentation-cases.R`.\n\n']; + + for (const snippet of snippets) { + await withFileEditor(snippet, 'R', async (_editor, doc) => { + // Type one newline character to trigger indentation + await type(doc, `\n${CURSOR}`); + snapshots.push(doc.getText()); + }); + } + + return snapshots.join('# --- \n'); +} diff --git a/extensions/positron-r/src/test/snapshots/.vscode/settings.json b/extensions/positron-r/src/test/snapshots/.vscode/settings.json new file mode 100644 index 00000000000..c755b1fd50a --- /dev/null +++ b/extensions/positron-r/src/test/snapshots/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "workbench.localHistory.enabled": false +} \ No newline at end of file diff --git a/extensions/positron-r/src/test/snapshots/indentation-cases.R b/extensions/positron-r/src/test/snapshots/indentation-cases.R new file mode 100644 index 00000000000..68f89514a57 --- /dev/null +++ b/extensions/positron-r/src/test/snapshots/indentation-cases.R @@ -0,0 +1,82 @@ +# Indentation snapshots. Edit cases in `indentation-cases.R` and observe results +# in `indentation-snapshots.R`. +# +# The cursor position is represented by a string containing angular brackets. A +# newline is typed at that position, triggering indentation rules. The result is +# saved in the snapshot file. +# +# Snippets are separated by `# ---`. This makes it possible to extract them and +# process them separately to prevent interferences between test cases. + +# --- +1 +"<>" + +# --- +1 + + 2 +"<>" + +# --- +data |>"<>" + +# --- +data |> + fn()"<>" + +# --- +# https://github.com/posit-dev/positron/issues/1727 +# FIXME +data |> + fn() +"<>" + +# --- +# https://github.com/posit-dev/positron/issues/1316 +data |> + fn() |>"<>" + +# --- +# With trailing whitespace +# https://github.com/posit-dev/positron/pull/1655#issuecomment-1780093395 +data |> + fn() |> "<>" + +# --- +data |> + fn1() |> + fn2() |>"<>" + +# --- +# FIXME +data |> + fn1() |> + fn2( + "arg" + )"<>" + +# --- +# https://github.com/posit-dev/positron-beta/discussions/46 +# FIXME +data |> + fn("<>") + +# --- +# FIXME +{ + fn(function() {}"<>") +} + +# --- +# FIXME +{ + fn(function() { + # + }"<>") +} + +# --- +for (i in NA) NULL"<>" + +# --- +# https://github.com/posit-dev/positron/issues/1880 +# FIXME +for (i in 1) fn()"<>" diff --git a/extensions/positron-r/src/test/snapshots/indentation-snapshots.R b/extensions/positron-r/src/test/snapshots/indentation-snapshots.R new file mode 100644 index 00000000000..06f87616b13 --- /dev/null +++ b/extensions/positron-r/src/test/snapshots/indentation-snapshots.R @@ -0,0 +1,88 @@ +# File generated from `indentation-cases.R`. + +# --- +1 + + "<>" + +# --- +1 + + 2 + + "<>" + +# --- +data |> + "<>" + +# --- +data |> + fn() +"<>" + +# --- +# https://github.com/posit-dev/positron/issues/1727 +# FIXME +data |> + fn() + + "<>" + +# --- +# https://github.com/posit-dev/positron/issues/1316 +data |> + fn() |> + "<>" + +# --- +# With trailing whitespace +# https://github.com/posit-dev/positron/pull/1655#issuecomment-1780093395 +data |> + fn() |> + "<>" + +# --- +data |> + fn1() |> + fn2() |> + "<>" + +# --- +# FIXME +data |> + fn1() |> + fn2( + "arg" + ) + "<>" + +# --- +# https://github.com/posit-dev/positron-beta/discussions/46 +# FIXME +data |> + fn( +"<>") + +# --- +# FIXME +{ + fn(function() {} +"<>") +} + +# --- +# FIXME +{ + fn(function() { + # + } +"<>") +} + +# --- +for (i in NA) NULL +"<>" + +# --- +# https://github.com/posit-dev/positron/issues/1880 +# FIXME +for (i in 1) fn() + "<>" From 16fe7ebab9138e973689d7bc65463fe6fd8f2139 Mon Sep 17 00:00:00 2001 From: Lionel Henry Date: Sat, 30 Mar 2024 07:40:50 +0100 Subject: [PATCH 4/7] Convert spaces to tabs consistently --- extensions/positron-r/src/test/indentation.test.ts | 2 +- .../positron-r/src/test/snapshots/indentation-cases.R | 6 +++--- .../positron-r/src/test/snapshots/indentation-snapshots.R | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/positron-r/src/test/indentation.test.ts b/extensions/positron-r/src/test/indentation.test.ts index 0b103680b90..1d048197c18 100644 --- a/extensions/positron-r/src/test/indentation.test.ts +++ b/extensions/positron-r/src/test/indentation.test.ts @@ -18,7 +18,7 @@ async function init() { // Prevents `ENOENT: no such file or directory` errors caused by us // deleting temporary editor files befor Code had the opportunity to - // save the user history of these files (see ) + // save the user history of these files. config.update('workbench.localHistory.enabled', false, vscode.ConfigurationTarget.Workspace); } diff --git a/extensions/positron-r/src/test/snapshots/indentation-cases.R b/extensions/positron-r/src/test/snapshots/indentation-cases.R index 68f89514a57..07c2f666fad 100644 --- a/extensions/positron-r/src/test/snapshots/indentation-cases.R +++ b/extensions/positron-r/src/test/snapshots/indentation-cases.R @@ -50,8 +50,8 @@ data |> data |> fn1() |> fn2( - "arg" - )"<>" + "arg" + )"<>" # --- # https://github.com/posit-dev/positron-beta/discussions/46 @@ -69,7 +69,7 @@ data |> # FIXME { fn(function() { - # + # }"<>") } diff --git a/extensions/positron-r/src/test/snapshots/indentation-snapshots.R b/extensions/positron-r/src/test/snapshots/indentation-snapshots.R index 06f87616b13..e480ffa32b2 100644 --- a/extensions/positron-r/src/test/snapshots/indentation-snapshots.R +++ b/extensions/positron-r/src/test/snapshots/indentation-snapshots.R @@ -50,9 +50,9 @@ data |> data |> fn1() |> fn2( - "arg" - ) - "<>" + "arg" + ) + "<>" # --- # https://github.com/posit-dev/positron-beta/discussions/46 @@ -72,7 +72,7 @@ data |> # FIXME { fn(function() { - # + # } "<>") } From 7f5e40e904ae9dbb9257c0f64dc9d40941472479 Mon Sep 17 00:00:00 2001 From: Lionel Henry Date: Mon, 1 Apr 2024 09:55:45 +0200 Subject: [PATCH 5/7] Remove trailing whitespace in fences --- .../positron-r/src/test/indentation.test.ts | 3 +- .../test/snapshots/indentation-snapshots.R | 28 +++++++++---------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/extensions/positron-r/src/test/indentation.test.ts b/extensions/positron-r/src/test/indentation.test.ts index 1d048197c18..df073788cce 100644 --- a/extensions/positron-r/src/test/indentation.test.ts +++ b/extensions/positron-r/src/test/indentation.test.ts @@ -36,7 +36,6 @@ suite('Indentation', () => { // Notify if snapshots were outdated assert.strictEqual(expected, current); - console.log('dirname: ', __dirname); }); }); @@ -58,5 +57,5 @@ async function regenerateIndentSnapshots() { }); } - return snapshots.join('# --- \n'); + return snapshots.join('# ---\n'); } diff --git a/extensions/positron-r/src/test/snapshots/indentation-snapshots.R b/extensions/positron-r/src/test/snapshots/indentation-snapshots.R index e480ffa32b2..a684a223f5b 100644 --- a/extensions/positron-r/src/test/snapshots/indentation-snapshots.R +++ b/extensions/positron-r/src/test/snapshots/indentation-snapshots.R @@ -1,24 +1,24 @@ # File generated from `indentation-cases.R`. -# --- +# --- 1 + "<>" -# --- +# --- 1 + 2 + "<>" -# --- +# --- data |> "<>" -# --- +# --- data |> fn() "<>" -# --- +# --- # https://github.com/posit-dev/positron/issues/1727 # FIXME data |> @@ -26,26 +26,26 @@ data |> "<>" -# --- +# --- # https://github.com/posit-dev/positron/issues/1316 data |> fn() |> "<>" -# --- +# --- # With trailing whitespace # https://github.com/posit-dev/positron/pull/1655#issuecomment-1780093395 data |> fn() |> "<>" -# --- +# --- data |> fn1() |> fn2() |> "<>" -# --- +# --- # FIXME data |> fn1() |> @@ -54,21 +54,21 @@ data |> ) "<>" -# --- +# --- # https://github.com/posit-dev/positron-beta/discussions/46 # FIXME data |> fn( "<>") -# --- +# --- # FIXME { fn(function() {} "<>") } -# --- +# --- # FIXME { fn(function() { @@ -77,11 +77,11 @@ data |> "<>") } -# --- +# --- for (i in NA) NULL "<>" -# --- +# --- # https://github.com/posit-dev/positron/issues/1880 # FIXME for (i in 1) fn() From 46f05ec98fe74a9d66605ce6ea847635c6c9e1d5 Mon Sep 17 00:00:00 2001 From: Lionel Henry Date: Tue, 2 Apr 2024 13:53:56 +0200 Subject: [PATCH 6/7] Use `EXTENSION_ROOT_DIR` --- extensions/positron-r/src/test/indentation.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/positron-r/src/test/indentation.test.ts b/extensions/positron-r/src/test/indentation.test.ts index df073788cce..6fc82cfa4d8 100644 --- a/extensions/positron-r/src/test/indentation.test.ts +++ b/extensions/positron-r/src/test/indentation.test.ts @@ -2,8 +2,9 @@ import * as vscode from 'vscode'; import * as assert from 'assert'; import * as fs from 'fs'; import { CURSOR, type, withFileEditor } from './editor-utils'; +import { EXTENSION_ROOT_DIR } from '../constants'; -const snapshotsFolder = `${__dirname}/../../src/test/snapshots`; +const snapshotsFolder = `${EXTENSION_ROOT_DIR}/src/test/snapshots`; const snippetsPath = `${snapshotsFolder}/indentation-cases.R`; const snapshotsPath = `${snapshotsFolder}/indentation-snapshots.R`; From 50324164dc46de14ba869cb58fd020c8f173d523 Mon Sep 17 00:00:00 2001 From: Lionel Henry Date: Tue, 2 Apr 2024 14:09:06 +0200 Subject: [PATCH 7/7] Include original case in snapshot --- .../positron-r/src/test/indentation.test.ts | 6 +- .../test/snapshots/indentation-snapshots.R | 60 +++++++++++++++++++ extensions/positron-r/src/util.ts | 15 +++++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/extensions/positron-r/src/test/indentation.test.ts b/extensions/positron-r/src/test/indentation.test.ts index 6fc82cfa4d8..ce1515c1710 100644 --- a/extensions/positron-r/src/test/indentation.test.ts +++ b/extensions/positron-r/src/test/indentation.test.ts @@ -3,6 +3,7 @@ import * as assert from 'assert'; import * as fs from 'fs'; import { CURSOR, type, withFileEditor } from './editor-utils'; import { EXTENSION_ROOT_DIR } from '../constants'; +import { removeLeadingLines } from '../util'; const snapshotsFolder = `${EXTENSION_ROOT_DIR}/src/test/snapshots`; const snippetsPath = `${snapshotsFolder}/indentation-cases.R`; @@ -51,10 +52,13 @@ async function regenerateIndentSnapshots() { const snapshots: string[] = ['# File generated from `indentation-cases.R`.\n\n']; for (const snippet of snippets) { + const bareSnippet = snippet.split('\n').slice(0, -1).join('\n'); + await withFileEditor(snippet, 'R', async (_editor, doc) => { // Type one newline character to trigger indentation await type(doc, `\n${CURSOR}`); - snapshots.push(doc.getText()); + const snapshot = removeLeadingLines(doc.getText(), /^$|^#/); + snapshots.push(bareSnippet + '\n# ->\n' + snapshot); }); } diff --git a/extensions/positron-r/src/test/snapshots/indentation-snapshots.R b/extensions/positron-r/src/test/snapshots/indentation-snapshots.R index a684a223f5b..035873c1316 100644 --- a/extensions/positron-r/src/test/snapshots/indentation-snapshots.R +++ b/extensions/positron-r/src/test/snapshots/indentation-snapshots.R @@ -1,19 +1,33 @@ # File generated from `indentation-cases.R`. # --- +1 +"<>" + +# -> 1 + "<>" # --- +1 + + 2 +"<>" + +# -> 1 + 2 + "<>" # --- +data |>"<>" + +# -> data |> "<>" # --- +data |> + fn()"<>" + +# -> data |> fn() "<>" @@ -21,6 +35,11 @@ data |> # --- # https://github.com/posit-dev/positron/issues/1727 # FIXME +data |> + fn() +"<>" + +# -> data |> fn() @@ -28,6 +47,10 @@ data |> # --- # https://github.com/posit-dev/positron/issues/1316 +data |> + fn() |>"<>" + +# -> data |> fn() |> "<>" @@ -35,11 +58,20 @@ data |> # --- # With trailing whitespace # https://github.com/posit-dev/positron/pull/1655#issuecomment-1780093395 +data |> + fn() |> "<>" + +# -> data |> fn() |> "<>" # --- +data |> + fn1() |> + fn2() |>"<>" + +# -> data |> fn1() |> fn2() |> @@ -47,6 +79,13 @@ data |> # --- # FIXME +data |> + fn1() |> + fn2( + "arg" + )"<>" + +# -> data |> fn1() |> fn2( @@ -57,12 +96,21 @@ data |> # --- # https://github.com/posit-dev/positron-beta/discussions/46 # FIXME +data |> + fn("<>") + +# -> data |> fn( "<>") # --- # FIXME +{ + fn(function() {}"<>") +} + +# -> { fn(function() {} "<>") @@ -70,6 +118,13 @@ data |> # --- # FIXME +{ + fn(function() { + # + }"<>") +} + +# -> { fn(function() { # @@ -78,11 +133,16 @@ data |> } # --- +for (i in NA) NULL"<>" + +# -> for (i in NA) NULL "<>" # --- # https://github.com/posit-dev/positron/issues/1880 # FIXME +for (i in 1) fn()"<>" +# -> for (i in 1) fn() "<>" diff --git a/extensions/positron-r/src/util.ts b/extensions/positron-r/src/util.ts index cc86dd8a64d..5175de529c5 100644 --- a/extensions/positron-r/src/util.ts +++ b/extensions/positron-r/src/util.ts @@ -48,3 +48,18 @@ export function extractValue(str: string, key: string, delim: string = '='): str const m = str.match(re); return m?.[1] ?? ''; } + +export function removeLeadingLines(x: string, pattern: RegExp): string { + const lines = x.split('\n'); + let output = lines; + + for (const line of lines) { + if (pattern.test(line)) { + output = output.slice(1); + continue; + } + break; + } + + return output.join('\n'); +}