From 80ae5823dd8fdb24c29d36ef1f03158d11c167de Mon Sep 17 00:00:00 2001 From: Ilya Bogdanov Date: Thu, 21 Nov 2024 16:19:04 +0400 Subject: [PATCH] Table.input instead of Table.new (#11612) --- CHANGELOG.md | 4 + app/gui/e2e/project-view/actions.ts | 8 +- .../GraphEditor/widgets/WidgetTableEditor.vue | 12 +- ...ent.test.ts => tableInputArgument.test.ts} | 226 +++++++++--------- ...leNewArgument.ts => tableInputArgument.ts} | 28 +-- .../project-view/mock/mockSuggestions.json | 20 ++ 6 files changed, 153 insertions(+), 145 deletions(-) rename app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/__tests__/{tableNewArgument.test.ts => tableInputArgument.test.ts} (66%) rename app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/{tableNewArgument.ts => tableInputArgument.ts} (95%) diff --git a/CHANGELOG.md b/CHANGELOG.md index e608d050a6..6fa5cbdec0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,9 @@ - ["Write" button in component menu allows to evaluate it separately from the rest of the workflow][11523]. - [The documentation editor can now display tables][11564] +- [Table Input Widget is now matched for Table.input method instead of + Table.new. Values must be string literals, and their content is parsed to the + suitable type][11612]. [11151]: https://github.com/enso-org/enso/pull/11151 [11271]: https://github.com/enso-org/enso/pull/11271 @@ -48,6 +51,7 @@ [11547]: https://github.com/enso-org/enso/pull/11547 [11523]: https://github.com/enso-org/enso/pull/11523 [11564]: https://github.com/enso-org/enso/pull/11564 +[11612]: https://github.com/enso-org/enso/pull/11612 #### Enso Standard Library diff --git a/app/gui/e2e/project-view/actions.ts b/app/gui/e2e/project-view/actions.ts index 7e9dbc0a37..96743db1f5 100644 --- a/app/gui/e2e/project-view/actions.ts +++ b/app/gui/e2e/project-view/actions.ts @@ -113,22 +113,22 @@ export async function createTableNode(page: Page) { // Adding `Table.new` component will display the widget await locate.addNewNodeButton(page).click() await expect(locate.componentBrowser(page)).toBeVisible() - await page.keyboard.type('Table.new') + await page.keyboard.type('Table.input') // Wait for CB entry to appear; this way we're sure about node name (binding). await expect(locate.componentBrowserSelectedEntry(page)).toHaveCount(1) - await expect(locate.componentBrowserSelectedEntry(page)).toHaveText('Table.new') + await expect(locate.componentBrowserSelectedEntry(page)).toHaveText('Table.input') await page.keyboard.press('Enter') const node = locate.graphNodeByBinding(page, 'table1') await expect(node).toHaveCount(1) await expect(node).toBeVisible() await mockMethodCallInfo( page, - { binding: 'table1', expr: 'Table.new' }, + { binding: 'table1', expr: 'Table.input' }, { methodPointer: { module: 'Standard.Table.Table', definedOnType: 'Standard.Table.Table.Table', - name: 'new', + name: 'input', }, notAppliedArguments: [0], }, diff --git a/app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor.vue b/app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor.vue index f250e82d7a..6172678827 100644 --- a/app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor.vue +++ b/app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor.vue @@ -3,10 +3,10 @@ import { WidgetInputIsSpecificMethodCall } from '@/components/GraphEditor/widget import TableHeader from '@/components/GraphEditor/widgets/WidgetTableEditor/TableHeader.vue' import { CELLS_LIMIT, - tableNewCallMayBeHandled, - useTableNewArgument, + tableInputCallMayBeHandled, + useTableInputArgument, type RowData, -} from '@/components/GraphEditor/widgets/WidgetTableEditor/tableNewArgument' +} from '@/components/GraphEditor/widgets/WidgetTableEditor/tableInputArgument' import ResizeHandles from '@/components/ResizeHandles.vue' import AgGridTableView from '@/components/shared/AgGridTableView.vue' import { injectGraphNavigator } from '@/providers/graphNavigator' @@ -55,7 +55,7 @@ const config = computed(() => { } }) -const { rowData, columnDefs, moveColumn, moveRow, pasteFromClipboard } = useTableNewArgument( +const { rowData, columnDefs, moveColumn, moveRow, pasteFromClipboard } = useTableInputArgument( () => props.input, graph, suggestionDb.entries, @@ -235,12 +235,12 @@ export const widgetDefinition = defineWidget( WidgetInputIsSpecificMethodCall({ module: 'Standard.Table.Table', definedOnType: 'Standard.Table.Table.Table', - name: 'new', + name: 'input', }), { priority: 999, score: (props) => { - if (!tableNewCallMayBeHandled(props.input.value)) return Score.Mismatch + if (!tableInputCallMayBeHandled(props.input.value)) return Score.Mismatch return Score.Perfect }, }, diff --git a/app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/__tests__/tableNewArgument.test.ts b/app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/__tests__/tableInputArgument.test.ts similarity index 66% rename from app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/__tests__/tableNewArgument.test.ts rename to app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/__tests__/tableInputArgument.test.ts index b23d7b8609..eee22374d3 100644 --- a/app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/__tests__/tableNewArgument.test.ts +++ b/app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/__tests__/tableInputArgument.test.ts @@ -4,9 +4,9 @@ import { NEW_COLUMN_ID, ROW_INDEX_HEADER, RowData, - tableNewCallMayBeHandled, - useTableNewArgument, -} from '@/components/GraphEditor/widgets/WidgetTableEditor/tableNewArgument' + tableInputCallMayBeHandled, + useTableInputArgument, +} from '@/components/GraphEditor/widgets/WidgetTableEditor/tableInputArgument' import { MenuItem } from '@/components/shared/AgGridTableView.vue' import { WidgetInput } from '@/providers/widgetRegistry' import { SuggestionDb } from '@/stores/suggestionDatabase' @@ -24,7 +24,7 @@ function suggestionDbWithNothing() { } function generateTableOfOnes(rows: number, cols: number) { - const code = `Table.new [${[...Array(cols).keys()].map((i) => `['Column #${i}', [${Array(rows).fill('1').join(',')}]]`).join(',')}]` + const code = `Table.input [${[...Array(cols).keys()].map((i) => `['Column #${i}', [${Array(rows).fill("'1'").join(',')}]]`).join(',')}]` const ast = Ast.parseExpression(code) assertDefined(ast) return ast @@ -38,7 +38,7 @@ assert(CELLS_LIMIT_SQRT === Math.floor(CELLS_LIMIT_SQRT)) test.each([ { - code: 'Table.new [["a", [1, 2, 3]], ["b", [4, 5, "six"]], ["empty", [Nothing, Standard.Base.Nothing, Nothing]]]', + code: "Table.input [['a', ['1', '2', '3']], ['b', ['4', '5', 'six']], ['empty', [Nothing, Standard.Base.Nothing, Nothing]]]", expectedColumnDefs: [ expectedRowIndexColumnDef, { headerName: 'a' }, @@ -47,34 +47,34 @@ test.each([ expectedNewColumnDef, ], expectedRows: [ - { [ROW_INDEX_HEADER]: 0, a: 1, b: 4, empty: null, '': null }, - { [ROW_INDEX_HEADER]: 1, a: 2, b: 5, empty: null, '': null }, - { [ROW_INDEX_HEADER]: 2, a: 3, b: 'six', empty: null, '': null }, + { [ROW_INDEX_HEADER]: 0, a: '1', b: '4', empty: null, '': null }, + { [ROW_INDEX_HEADER]: 1, a: '2', b: '5', empty: null, '': null }, + { [ROW_INDEX_HEADER]: 2, a: '3', b: 'six', empty: null, '': null }, { [ROW_INDEX_HEADER]: 3, a: null, b: null, empty: null, '': null }, ], }, { - code: 'Table.new []', + code: 'Table.input []', expectedColumnDefs: [expectedRowIndexColumnDef, expectedNewColumnDef], expectedRows: [{ [ROW_INDEX_HEADER]: 0, '': null }], }, { - code: 'Table.new', + code: 'Table.input', expectedColumnDefs: [expectedRowIndexColumnDef, expectedNewColumnDef], expectedRows: [{ [ROW_INDEX_HEADER]: 0, '': null }], }, { - code: 'Table.new _', + code: 'Table.input _', expectedColumnDefs: [expectedRowIndexColumnDef, expectedNewColumnDef], expectedRows: [{ [ROW_INDEX_HEADER]: 0, '': null }], }, { - code: 'Table.new [["a", []]]', + code: 'Table.input [["a", []]]', expectedColumnDefs: [expectedRowIndexColumnDef, { headerName: 'a' }, expectedNewColumnDef], expectedRows: [{ [ROW_INDEX_HEADER]: 0, a: null, '': null }], }, { - code: 'Table.new [["a", [1,,2]], ["b", [3, 4,]], ["c", [, 5, 6]], ["d", [,,]]]', + code: "Table.input [['a', ['1',,'2']], ['b', ['3', '4',]], ['c', [, '5', '6']], ['d', [,,]]]", expectedColumnDefs: [ expectedRowIndexColumnDef, { headerName: 'a' }, @@ -84,21 +84,21 @@ test.each([ expectedNewColumnDef, ], expectedRows: [ - { [ROW_INDEX_HEADER]: 0, a: 1, b: 3, c: null, d: null, '': null }, - { [ROW_INDEX_HEADER]: 1, a: null, b: 4, c: 5, d: null, '': null }, - { [ROW_INDEX_HEADER]: 2, a: 2, b: null, c: 6, d: null, '': null }, + { [ROW_INDEX_HEADER]: 0, a: '1', b: '3', c: null, d: null, '': null }, + { [ROW_INDEX_HEADER]: 1, a: null, b: '4', c: '5', d: null, '': null }, + { [ROW_INDEX_HEADER]: 2, a: '2', b: null, c: '6', d: null, '': null }, { [ROW_INDEX_HEADER]: 3, a: null, b: null, c: null, d: null, '': null }, ], }, ])('Read table from $code', ({ code, expectedColumnDefs, expectedRows }) => { const ast = Ast.parseExpression(code) assertDefined(ast) - expect(tableNewCallMayBeHandled(ast)).toBeTruthy() + expect(tableInputCallMayBeHandled(ast)).toBeTruthy() const input = WidgetInput.FromAst(ast) const startEdit = vi.fn() const addMissingImports = vi.fn() const onUpdate = vi.fn() - const tableNewArgs = useTableNewArgument( + const tableNewArgs = useTableInputArgument( input, { startEdit, addMissingImports }, suggestionDbWithNothing(), @@ -160,7 +160,7 @@ test.each([ 'Allowed actions in table near limit (rows: $rows, cols: $cols)', ({ rows, cols, expectNewRowEnabled, expectNewColEnabled }) => { const input = WidgetInput.FromAst(generateTableOfOnes(rows, cols)) - const tableNewArgs = useTableNewArgument( + const tableNewArgs = useTableInputArgument( input, { startEdit: vi.fn(), addMissingImports: vi.fn() }, suggestionDbWithNothing(), @@ -174,16 +174,17 @@ test.each([ ) test.each([ - 'Table.new 14', - 'Table.new array1', - "Table.new ['a', [123]]", - "Table.new [['a', [123]], ['b', [124], []]]", - "Table.new [['a', [123]], ['a'.repeat 170, [123]]]", - "Table.new [['a', [1, 2, 3, 3 + 1]]]", + 'Table.input 14', + 'Table.input array1', + "Table.input ['a', ['123']]", + "Table.input [['a', [123]]]", + "Table.input [['a', ['123']], ['b', ['124'], []]]", + "Table.input [['a', ['123']], ['a'.repeat 170, ['123']]]", + "Table.input [['a', ['1', '2', '3', 3 + 1]]]", ])('"%s" is not valid input for Table Editor Widget', (code) => { const ast = Ast.parseExpression(code) assertDefined(ast) - expect(tableNewCallMayBeHandled(ast)).toBeFalsy() + expect(tableInputCallMayBeHandled(ast)).toBeFalsy() }) function tableEditFixture(code: string, expectedCode: string) { @@ -207,7 +208,7 @@ function tableEditFixture(code: string, expectedCode: string) { }, ]) }) - const tableNewArgs = useTableNewArgument( + const tableNewArgs = useTableInputArgument( input, { startEdit, addMissingImports }, suggestionDbWithNothing(), @@ -223,62 +224,56 @@ function tableEditFixture(code: string, expectedCode: string) { test.each([ { - code: "Table.new [['a', [1, 2, 3]], ['b', [4, 5, 6]]]", - description: 'Edit number', - edit: { column: 1, row: 1, value: -22 }, - expected: "Table.new [['a', [1, -22, 3]], ['b', [4, 5, 6]]]", - }, - { - code: "Table.new [['a', [1, 2, 3]], ['b', [4, 5, 6]]]", - description: 'Edit string', + code: "Table.input [['a', ['1', '2', '3']], ['b', ['4', '5', '6']]]", + description: 'Edit value', edit: { column: 1, row: 1, value: 'two' }, - expected: "Table.new [['a', [1, 'two', 3]], ['b', [4, 5, 6]]]", + expected: "Table.input [['a', ['1', 'two', '3']], ['b', ['4', '5', '6']]]", }, { - code: "Table.new [['a', [1, 2, 3]], ['b', [4, 5, 6]]]", + code: "Table.input [['a', ['1', '2', '3']], ['b', ['4', '5', '6']]]", description: 'Put blank value', edit: { column: 2, row: 1, value: '' }, - expected: "Table.new [['a', [1, 2, 3]], ['b', [4, Nothing, 6]]]", + expected: "Table.input [['a', ['1', '2', '3']], ['b', ['4', Nothing, '6']]]", importExpected: true, }, { - code: "Table.new [['a', [1, 2, 3]], ['b', [4, 5, 6]]]", + code: "Table.input [['a', ['1', '2', '3']], ['b', ['4', '5', '6']]]", description: 'Add new row', - edit: { column: 1, row: 3, value: 4.5 }, - expected: "Table.new [['a', [1, 2, 3, 4.5]], ['b', [4, 5, 6, Nothing]]]", + edit: { column: 1, row: 3, value: '4.5' }, + expected: "Table.input [['a', ['1', '2', '3', '4.5']], ['b', ['4', '5', '6', Nothing]]]", importExpected: true, }, { - code: "Table.new [['a', []], ['b', []]]", + code: "Table.input [['a', []], ['b', []]]", description: 'Add first row', edit: { column: 2, row: 0, value: 'val' }, - expected: "Table.new [['a', [Nothing]], ['b', ['val']]]", + expected: "Table.input [['a', [Nothing]], ['b', ['val']]]", importExpected: true, }, { - code: "Table.new [['a', [1, ,3]]]", + code: "Table.input [['a', ['1', ,'3']]]", description: 'Set missing value', - edit: { column: 1, row: 1, value: 2 }, - expected: "Table.new [['a', [1, 2 ,3]]]", + edit: { column: 1, row: 1, value: '2' }, + expected: "Table.input [['a', ['1', '2' ,'3']]]", }, { - code: "Table.new [['a', [, 2, 3]]]", + code: "Table.input [['a', [, '2', '3']]]", description: 'Set missing value at first row', - edit: { column: 1, row: 0, value: 1 }, - expected: "Table.new [['a', [1, 2, 3]]]", + edit: { column: 1, row: 0, value: '1' }, + expected: "Table.input [['a', ['1', '2', '3']]]", }, { - code: "Table.new [['a', [1, 2,]]]", + code: "Table.input [['a', ['1', '2',]]]", description: 'Set missing value at last row', - edit: { column: 1, row: 2, value: 3 }, - expected: "Table.new [['a', [1, 2, 3]]]", + edit: { column: 1, row: 2, value: '3' }, + expected: "Table.input [['a', ['1', '2', '3']]]", }, { - code: "Table.new [['a', [1, 2]], ['a', [3, 4]]]", + code: "Table.input [['a', ['1', '2']], ['a', ['3', '4']]]", description: 'Edit with duplicated column name', - edit: { column: 1, row: 1, value: 5 }, - expected: "Table.new [['a', [1, 5]], ['a', [3, 4]]]", + edit: { column: 1, row: 1, value: '5' }, + expected: "Table.input [['a', ['1', '5']], ['a', ['3', '4']]]", }, ])('Edit table $code: $description', ({ code, edit, expected, importExpected }) => { const { tableNewArgs, onUpdate, addMissingImports } = tableEditFixture(code, expected) @@ -295,21 +290,21 @@ test.each([ test.each([ { - code: "Table.new [['a', [1, 2, 3]], ['b', [4, 5, 6]]]", - expected: `Table.new [['a', [1, 2, 3]], ['b', [4, 5, 6]], ['${DEFAULT_COLUMN_PREFIX}3', [Nothing, Nothing, Nothing]]]`, + code: "Table.input [['a', ['1', '2', '3']], ['b', ['4', '5', '6']]]", + expected: `Table.input [['a', ['1', '2', '3']], ['b', ['4', '5', '6']], ['${DEFAULT_COLUMN_PREFIX}3', [Nothing, Nothing, Nothing]]]`, importExpected: true, }, { - code: 'Table.new []', - expected: `Table.new [['${DEFAULT_COLUMN_PREFIX}1', []]]`, + code: 'Table.input []', + expected: `Table.input [['${DEFAULT_COLUMN_PREFIX}1', []]]`, }, { - code: 'Table.new', - expected: `Table.new [['${DEFAULT_COLUMN_PREFIX}1', []]]`, + code: 'Table.input', + expected: `Table.input [['${DEFAULT_COLUMN_PREFIX}1', []]]`, }, { - code: 'Table.new _', - expected: `Table.new [['${DEFAULT_COLUMN_PREFIX}1', []]]`, + code: 'Table.input _', + expected: `Table.input [['${DEFAULT_COLUMN_PREFIX}1', []]]`, }, ])('Add column to table $code', ({ code, expected, importExpected }) => { const { tableNewArgs, onUpdate, addMissingImports } = tableEditFixture(code, expected) @@ -340,24 +335,24 @@ function getCustomMenuItemByName( test.each([ { - code: "Table.new [['a', [1, 2, 3]], ['b', [4, 5, 6]]]", + code: "Table.input [['a', ['1', '2', '3']], ['b', ['4', '5', '6']]]", removedRowIndex: 0, - expected: "Table.new [['a', [2, 3]], ['b', [5, 6]]]", + expected: "Table.input [['a', ['2', '3']], ['b', ['5', '6']]]", }, { - code: "Table.new [['a', [1, 2, 3]], ['b', [4, 5, 6]]]", + code: "Table.input [['a', ['1', '2', '3']], ['b', ['4', '5', '6']]]", removedRowIndex: 1, - expected: "Table.new [['a', [1, 3]], ['b', [4, 6]]]", + expected: "Table.input [['a', ['1', '3']], ['b', ['4', '6']]]", }, { - code: "Table.new [['a', [1, 2, 3]], ['b', [4, 5, 6]]]", + code: "Table.input [['a', ['1', '2', '3']], ['b', ['4', '5', '6']]]", removedRowIndex: 2, - expected: "Table.new [['a', [1, 2]], ['b', [4, 5]]]", + expected: "Table.input [['a', ['1', '2']], ['b', ['4', '5']]]", }, { - code: "Table.new [['a', [1]], ['b', [4]]]", + code: "Table.input [['a', ['1']], ['b', ['4']]]", removedRowIndex: 0, - expected: "Table.new [['a', []], ['b', []]]", + expected: "Table.input [['a', []], ['b', []]]", }, ])('Remove $removedRowIndex row in $code', ({ code, removedRowIndex, expected }) => { const { tableNewArgs, onUpdate, addMissingImports, gridApi } = tableEditFixture(code, expected) @@ -376,24 +371,24 @@ test.each([ test.each([ { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]], ['c', [5, 6]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']], ['c', ['5', '6']]]", removedColIndex: 1, - expected: "Table.new [['b', [3, 4]], ['c', [5, 6]]]", + expected: "Table.input [['b', ['3', '4']], ['c', ['5', '6']]]", }, { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]], ['c', [5, 6]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']], ['c', ['5', '6']]]", removedColIndex: 2, - expected: "Table.new [['a', [1, 2]], ['c', [5, 6]]]", + expected: "Table.input [['a', ['1', '2']], ['c', ['5', '6']]]", }, { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]], ['c', [5, 6]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']], ['c', ['5', '6']]]", removedColIndex: 3, - expected: "Table.new [['a', [1, 2]], ['b', [3, 4]]]", + expected: "Table.input [['a', ['1', '2']], ['b', ['3', '4']]]", }, { - code: "Table.new [['a', [1, 2]]]", + code: "Table.input [['a', ['1', '2']]]", removedColIndex: 1, - expected: 'Table.new []', + expected: 'Table.input []', }, ])('Remove $removedColIndex column in $code', ({ code, removedColIndex, expected }) => { const { tableNewArgs, onUpdate, addMissingImports, gridApi } = tableEditFixture(code, expected) @@ -414,16 +409,16 @@ test.each([ test.each([ { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]], ['c', [5, 6]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']], ['c', ['5', '6']]]", fromIndex: 1, toIndex: 3, - expected: "Table.new [['b', [3, 4]], ['c', [5, 6]], ['a', [1, 2]]]", + expected: "Table.input [['b', ['3', '4']], ['c', ['5', '6']], ['a', ['1', '2']]]", }, { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]], ['c', [5, 6]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']], ['c', ['5', '6']]]", fromIndex: 3, toIndex: 2, - expected: "Table.new [['a', [1, 2]], ['c', [5, 6]], ['b', [3, 4]]]", + expected: "Table.input [['a', ['1', '2']], ['c', ['5', '6']], ['b', ['3', '4']]]", }, ])( 'Move column $fromIndex to $toIndex in table $code', @@ -439,22 +434,22 @@ test.each([ test.each([ { - code: "Table.new [['a', [1, 2, 3]], ['b', [4, 5, 6]]]", + code: "Table.input [['a', ['1', '2', '3']], ['b', ['4', '5', '6']]]", fromIndex: 1, toIndex: 2, - expected: "Table.new [['a', [1, 3, 2]], ['b', [4, 6, 5]]]", + expected: "Table.input [['a', ['1', '3', '2']], ['b', ['4', '6', '5']]]", }, { - code: "Table.new [['a', [1, 2, 3]], ['b', [4, 5, 6]]]", + code: "Table.input [['a', ['1', '2', '3']], ['b', ['4', '5', '6']]]", fromIndex: 2, toIndex: 0, - expected: "Table.new [['a', [3, 1, 2]], ['b', [6, 4, 5]]]", + expected: "Table.input [['a', ['3', '1', '2']], ['b', ['6', '4', '5']]]", }, { - code: "Table.new [['a', [1, 2, 3]], ['b', [4, 5, 6]]]", + code: "Table.input [['a', ['1', '2', '3']], ['b', ['4', '5', '6']]]", fromIndex: 1, toIndex: -1, - expected: "Table.new [['a', [1, 2, 3]], ['b', [4, 5, 6]]]", + expected: "Table.input [['a', ['1', '2', '3']], ['b', ['4', '5', '6']]]", }, ])('Move row $fromIndex to $toIndex in table $code', ({ code, fromIndex, toIndex, expected }) => { const { tableNewArgs, onUpdate, addMissingImports } = tableEditFixture(code, expected) @@ -467,100 +462,100 @@ test.each([ test.each([ { - code: 'Table.new', + code: 'Table.input', focused: { rowIndex: 0, colIndex: 1 }, data: [ ['1', '3'], ['2', '4'], ], - expected: `Table.new [['${DEFAULT_COLUMN_PREFIX}1', [1, 2]], ['${DEFAULT_COLUMN_PREFIX}2', [3, 4]]]`, + expected: `Table.input [['${DEFAULT_COLUMN_PREFIX}1', ['1', '2']], ['${DEFAULT_COLUMN_PREFIX}2', ['3', '4']]]`, }, { - code: 'Table.new []', + code: 'Table.input []', focused: { rowIndex: 0, colIndex: 1 }, data: [ ['1', '3'], ['2', '4'], ], - expected: `Table.new [['${DEFAULT_COLUMN_PREFIX}1', [1, 2]], ['${DEFAULT_COLUMN_PREFIX}2', [3, 4]]]`, + expected: `Table.input [['${DEFAULT_COLUMN_PREFIX}1', ['1', '2']], ['${DEFAULT_COLUMN_PREFIX}2', ['3', '4']]]`, }, { - code: 'Table.new []', + code: 'Table.input []', focused: { rowIndex: 0, colIndex: 1 }, data: [['a single cell']], - expected: `Table.new [['${DEFAULT_COLUMN_PREFIX}1', ['a single cell']]]`, + expected: `Table.input [['${DEFAULT_COLUMN_PREFIX}1', ['a single cell']]]`, }, { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']]]", focused: { rowIndex: 0, colIndex: 1 }, data: [['a single cell']], - expected: "Table.new [['a', ['a single cell', 2]], ['b', [3, 4]]]", + expected: "Table.input [['a', ['a single cell', '2']], ['b', ['3', '4']]]", }, { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']]]", focused: { rowIndex: 1, colIndex: 2 }, data: [['a single cell']], - expected: "Table.new [['a', [1, 2]], ['b', [3, 'a single cell']]]", + expected: "Table.input [['a', ['1', '2']], ['b', ['3', 'a single cell']]]", }, { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']]]", focused: { rowIndex: 2, colIndex: 2 }, data: [['a single cell']], - expected: "Table.new [['a', [1, 2, Nothing]], ['b', [3, 4, 'a single cell']]]", + expected: "Table.input [['a', ['1', '2', Nothing]], ['b', ['3', '4', 'a single cell']]]", importExpected: true, }, { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']]]", focused: { rowIndex: 1, colIndex: 3 }, data: [['a single cell']], - expected: `Table.new [['a', [1, 2]], ['b', [3, 4]], ['${DEFAULT_COLUMN_PREFIX}3', [Nothing, 'a single cell']]]`, + expected: `Table.input [['a', ['1', '2']], ['b', ['3', '4']], ['${DEFAULT_COLUMN_PREFIX}3', [Nothing, 'a single cell']]]`, importExpected: true, }, { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']]]", focused: { rowIndex: 0, colIndex: 1 }, data: [ ['5', '7'], ['6', '8'], ], - expected: "Table.new [['a', [5, 6]], ['b', [7, 8]]]", + expected: "Table.input [['a', ['5', '6']], ['b', ['7', '8']]]", }, { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']]]", focused: { rowIndex: 1, colIndex: 1 }, data: [ ['5', '7'], ['6', '8'], ], - expected: "Table.new [['a', [1, 5, 6]], ['b', [3, 7, 8]]]", + expected: "Table.input [['a', ['1', '5', '6']], ['b', ['3', '7', '8']]]", }, { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']]]", focused: { rowIndex: 0, colIndex: 2 }, data: [ ['5', '7'], ['6', '8'], ], - expected: `Table.new [['a', [1, 2]], ['b', [5, 6]], ['${DEFAULT_COLUMN_PREFIX}3', [7, 8]]]`, + expected: `Table.input [['a', ['1', '2']], ['b', ['5', '6']], ['${DEFAULT_COLUMN_PREFIX}3', ['7', '8']]]`, }, { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']]]", focused: { rowIndex: 1, colIndex: 2 }, data: [ ['5', '7'], ['6', '8'], ], - expected: `Table.new [['a', [1, 2, Nothing]], ['b', [3, 5, 6]], ['${DEFAULT_COLUMN_PREFIX}3', [Nothing, 7, 8]]]`, + expected: `Table.input [['a', ['1', '2', Nothing]], ['b', ['3', '5', '6']], ['${DEFAULT_COLUMN_PREFIX}3', [Nothing, '7', '8']]]`, importExpected: true, }, { - code: "Table.new [['a', [1, 2]], ['b', [3, 4]]]", + code: "Table.input [['a', ['1', '2']], ['b', ['3', '4']]]", focused: { rowIndex: 2, colIndex: 2 }, data: [ ['5', '7'], ['6', '8'], ], - expected: `Table.new [['a', [1, 2, Nothing, Nothing]], ['b', [3, 4, 5, 6]], ['${DEFAULT_COLUMN_PREFIX}3', [Nothing, Nothing, 7, 8]]]`, + expected: `Table.input [['a', ['1', '2', Nothing, Nothing]], ['b', ['3', '4', '5', '6']], ['${DEFAULT_COLUMN_PREFIX}3', [Nothing, Nothing, '7', '8']]]`, importExpected: true, }, ])( @@ -593,12 +588,13 @@ test('Pasted data which would exceed cells limit is truncated', () => { let cellCount = 0 inputAst.visitRecursive((ast: Ast.Ast | Ast.Token) => { if (ast instanceof Ast.Token) return - if (ast instanceof Ast.NumericLiteral || ast.code() === 'Nothing') cellCount++ + if (ast instanceof Ast.TextLiteral && ast.code().startsWith("'Column #")) return + if (ast instanceof Ast.TextLiteral || ast.code() === 'Nothing') cellCount++ }) expect(cellCount).toBe(CELLS_LIMIT) }) const addMissingImports = vi.fn() - const tableNewArgs = useTableNewArgument( + const tableNewArgs = useTableInputArgument( input, { startEdit, addMissingImports }, suggestionDbWithNothing(), diff --git a/app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/tableNewArgument.ts b/app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/tableInputArgument.ts similarity index 95% rename from app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/tableNewArgument.ts rename to app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/tableInputArgument.ts index b84028250c..caae149062 100644 --- a/app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/tableNewArgument.ts +++ b/app/gui/src/project-view/components/GraphEditor/widgets/WidgetTableEditor/tableInputArgument.ts @@ -4,7 +4,6 @@ import { type RequiredImport, requiredImportsByFQN } from '@/stores/graph/import import type { SuggestionDb } from '@/stores/suggestionDatabase' import { assert } from '@/util/assert' import { Ast } from '@/util/ast' -import { tryEnsoToNumber, tryNumberToEnso } from '@/util/ast/abstract' import { findIndexOpt } from '@/util/data/array' import { Err, Ok, type Result, transposeResult, unwrapOrWithLog } from '@/util/data/result' import { qnLastSegment, type QualifiedName } from '@/util/qualifiedName' @@ -41,7 +40,7 @@ export type RowData = { */ export interface ColumnDef extends ColDef { valueGetter: ({ data }: { data: RowData | undefined }) => any - valueSetter?: ({ data, newValue }: { data: RowData; newValue: any }) => boolean + valueSetter?: ({ data, newValue }: { data: RowData; newValue: string }) => boolean mainMenuItems: (string | MenuItem)[] contextMenuItems: (string | MenuItem)[] rowDrag?: ({ data }: { data: RowData | undefined }) => boolean @@ -54,11 +53,7 @@ namespace cellValueConversion { if (ast instanceof Ast.TextLiteral) return Ok(ast.rawTextContent) else if (ast instanceof Ast.Ident && ast.code() === NOTHING_NAME) return Ok(null) else if (ast instanceof Ast.PropertyAccess && ast.rhs.code() === NOTHING_NAME) return Ok(null) - else { - const asNumber = tryEnsoToNumber(ast) - if (asNumber != null) return Ok(asNumber) - else return Err('Ast is not convertible to AGGrid value') - } + else return Err('Ast is not convertible to AGGrid value') } /** @@ -72,16 +67,9 @@ namespace cellValueConversion { ): { ast: Ast.Owned; requireNothingImport: boolean } { if (value == null || value === '') { return { ast: Ast.Ident.new(module, 'Nothing' as Ast.Identifier), requireNothingImport: true } - } else if (typeof value === 'number') { - return { - ast: tryNumberToEnso(value, module) ?? Ast.TextLiteral.new(`${value}`, module), - requireNothingImport: false, - } } else { return { - ast: - Ast.NumericLiteral.tryParseWithSign(`${value}`, module) ?? - Ast.TextLiteral.new(`${value}`, module), + ast: Ast.TextLiteral.new(`${value}`, module), requireNothingImport: false, } } @@ -92,7 +80,7 @@ function retrieveColumnsAst(call: Ast.Expression): Result, graph: { startEdit(): Ast.MutableModule diff --git a/app/gui/src/project-view/mock/mockSuggestions.json b/app/gui/src/project-view/mock/mockSuggestions.json index 058e4bb57c..70a64d3ce2 100644 --- a/app/gui/src/project-view/mock/mockSuggestions.json +++ b/app/gui/src/project-view/mock/mockSuggestions.json @@ -1047,6 +1047,26 @@ "documentation": "", "annotations": [] }, + { + "type": "method", + "module": "Standard.Table.Table", + "name": "input", + "arguments": [ + { + "name": "columns", + "reprType": "Standard.Base.Data.Vector.Vector Standard.Base.Data.Vector.Vector | Standard.Table.Column.Column", + "isSuspended": false, + "hasDefault": false, + "defaultValue": null, + "tagValues": null + } + ], + "selfType": "Standard.Table.Table.Table", + "returnType": "Standard.Table.Table.Table", + "isStatic": true, + "documentation": "", + "annotations": [] + }, { "type": "method", "module": "Standard.Table.Table",