diff --git a/.claude/skills/view-chain-layout/SKILL.md b/.claude/skills/view-chain-layout/SKILL.md index 2f9aa6da..3be28935 100644 --- a/.claude/skills/view-chain-layout/SKILL.md +++ b/.claude/skills/view-chain-layout/SKILL.md @@ -126,9 +126,10 @@ first child is another `ele( )`, blank before every `end( )`, none after an The rule is the abap2UI5-linter's **`chain-house-layout`**. It checks rules 1-4 and carries fixes, so `--fix` reformats a drifted chain. The rewrite only ever touches whitespace *between* chain segments and the indent of a continuation -line that is not itself content, and it verifies that collapsing every run of -code-whitespace leaves the source identical — **a layout fix can never change -what the view builds.** Rules 5-7 and the blank lines stay reviewer-enforced. +line that is not itself content — **by construction, not by a check**: the +fixes run to a fixed point and nothing re-parses the result against the +source, so read the diff of a `--fix` run before committing it. Rules 5-7 and +the blank lines stay reviewer-enforced. It is the linter's one **opt-in** rule (`OPT_IN` in its `findings.mjs`): it is not emitted at all until a config asks for it, because it encodes one house diff --git a/package-lock.json b/package-lock.json index f157c210..45f3aec6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,8 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "@abap2ui5/linter": "^0.8.5", - "@abap2ui5/linter-render": "^0.8.5", + "@abap2ui5/linter": "^0.9.0", + "@abap2ui5/linter-render": "^0.9.0", "@abaplint/cli": "^2.120.75", "@openui5/sap.f": "1.152.0", "@openui5/sap.m": "1.152.0", @@ -27,9 +27,9 @@ } }, "node_modules/@abap2ui5/linter": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@abap2ui5/linter/-/linter-0.8.5.tgz", - "integrity": "sha512-GSqWvLRhFU8F5dOv/DT/nbouVN4B3zWRvPibaK1SCXzpW6bj5LcYDIJPDVce7g8Qoz8WkFaJkw3aTn/5OKqJmA==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@abap2ui5/linter/-/linter-0.9.0.tgz", + "integrity": "sha512-DyhJGFxZzXGH6Ifl3W5KhdDTzy1IFc/uCV0l/2E+cjVrpOc319tXmMqBg6hb3kE3Jw9phIGjADjWPyiiGzXKJg==", "dev": true, "license": "MIT", "workspaces": [ @@ -43,7 +43,7 @@ "node": ">=22" }, "peerDependencies": { - "@abap2ui5/linter-render": ">=0.8.0 <0.9.0", + "@abap2ui5/linter-render": ">=0.8.0 <0.10.0", "@abap2ui5/render-runtime": ">=0.1.0 <0.8.0" }, "peerDependenciesMeta": { @@ -56,58 +56,144 @@ } }, "node_modules/@abap2ui5/linter-render": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@abap2ui5/linter-render/-/linter-render-0.8.5.tgz", - "integrity": "sha512-WPGTyqCI7B/B/0gD7sC/DeuwXdwQXI+f+fo1tWWtHGuoKe1OSe6oVN1AYxUEaP3sBSKG92EMeXBIGbLMU2B3Cw==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@abap2ui5/linter-render/-/linter-render-0.9.0.tgz", + "integrity": "sha512-3j7SiCDqsJGapawHUPXm5MNBADnWQWlTyQe91q0XgV3ngRpVyWqrEYhZ3xCcQCyyPwI6YMlQrJAewOet0PnX4g==", "dev": true, "license": "MIT", "dependencies": { - "@openui5/sap.f": "1.152.0", - "@openui5/sap.m": "1.152.0", - "@openui5/sap.tnt": "1.152.0", - "@openui5/sap.ui.codeeditor": "1.152.0", - "@openui5/sap.ui.core": "1.152.0", - "@openui5/sap.ui.integration": "1.152.0", - "@openui5/sap.ui.layout": "1.152.0", - "@openui5/sap.ui.table": "1.152.0", - "@openui5/sap.ui.unified": "1.152.0", - "@openui5/sap.uxap": "1.152.0", - "@openui5/themelib_sap_horizon": "1.152.0", + "@openui5/sap.f": "1.153.0", + "@openui5/sap.m": "1.153.0", + "@openui5/sap.tnt": "1.153.0", + "@openui5/sap.ui.codeeditor": "1.153.0", + "@openui5/sap.ui.core": "1.153.0", + "@openui5/sap.ui.integration": "1.153.0", + "@openui5/sap.ui.layout": "1.153.0", + "@openui5/sap.ui.table": "1.153.0", + "@openui5/sap.ui.unified": "1.153.0", + "@openui5/sap.uxap": "1.153.0", + "@openui5/themelib_sap_horizon": "1.153.0", "less-openui5": "^0.12.0", - "playwright": "^1.61.1" + "playwright": "^1.64.0" }, "engines": { "node": ">=22" } }, + "node_modules/@abap2ui5/linter-render/node_modules/@openui5/sap.f": { + "version": "1.153.0", + "resolved": "https://registry.npmjs.org/@openui5/sap.f/-/sap.f-1.153.0.tgz", + "integrity": "sha512-HLlfiti8xwZytbf81yFkbHH/8NHLH/+1WMe3lhoqaQEDZBmkuGBkrApvv+YrrLuU1BVEAlZuOyL7//rptHtdzw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@openui5/sap.m": "1.153.0", + "@openui5/sap.ui.core": "1.153.0", + "@openui5/sap.ui.layout": "1.153.0" + } + }, + "node_modules/@abap2ui5/linter-render/node_modules/@openui5/sap.m": { + "version": "1.153.0", + "resolved": "https://registry.npmjs.org/@openui5/sap.m/-/sap.m-1.153.0.tgz", + "integrity": "sha512-afDAICMYaBBTGyjakB4tbWNSFW+4b6uyJubmUzoQIeZl0LqpH6Pf73XEUxz4NBCiNd8QSNiR7En7n3l5vvkD3w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@openui5/sap.ui.core": "1.153.0", + "@openui5/sap.ui.layout": "1.153.0", + "@openui5/sap.ui.unified": "1.153.0" + } + }, + "node_modules/@abap2ui5/linter-render/node_modules/@openui5/sap.tnt": { + "version": "1.153.0", + "resolved": "https://registry.npmjs.org/@openui5/sap.tnt/-/sap.tnt-1.153.0.tgz", + "integrity": "sha512-gHztjle7WP4WIq9nXCGpFmZT48HHo7gXxMXUJ6NH88sp6y38PA7V2eLofsvpD+NaNXlgyK8kQuh79QXlJUwEJQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@openui5/sap.m": "1.153.0", + "@openui5/sap.ui.core": "1.153.0" + } + }, "node_modules/@abap2ui5/linter-render/node_modules/@openui5/sap.ui.codeeditor": { - "version": "1.152.0", - "resolved": "https://registry.npmjs.org/@openui5/sap.ui.codeeditor/-/sap.ui.codeeditor-1.152.0.tgz", - "integrity": "sha512-SZ+++6DIMltcYW1xhnSuYwEZtthIG4FjxLh+QWVC1UcfRfe//N1jTfJkK7GvR1Gs5QPe8Tzl5zbbknn+8bMiFQ==", + "version": "1.153.0", + "resolved": "https://registry.npmjs.org/@openui5/sap.ui.codeeditor/-/sap.ui.codeeditor-1.153.0.tgz", + "integrity": "sha512-vEzHi3a0LM01lSN2gyz23EeqHu02tjPCwOJ/3D6fs+qiGNrwRCtH0MdszFa/s+BdPWXsSR4dp9USPPlFaRg79w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@openui5/sap.ui.core": "1.152.0" + "@openui5/sap.ui.core": "1.153.0" } }, + "node_modules/@abap2ui5/linter-render/node_modules/@openui5/sap.ui.core": { + "version": "1.153.0", + "resolved": "https://registry.npmjs.org/@openui5/sap.ui.core/-/sap.ui.core-1.153.0.tgz", + "integrity": "sha512-kJQLIqfDCURHSNpUTJBgDEVCuH31FmXyc8xDvV/JwATQgyJGKMp3t1KIeUyLaOfSh5ux+iA7vHznSPZ0DVsNsA==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/@abap2ui5/linter-render/node_modules/@openui5/sap.ui.integration": { - "version": "1.152.0", - "resolved": "https://registry.npmjs.org/@openui5/sap.ui.integration/-/sap.ui.integration-1.152.0.tgz", - "integrity": "sha512-hOz8q4E9CWxOYSXAo+Ps69009+RAFBClnd/0Pv4uWH7Zl/ETiQTyeIm3jrX3O1Bt7zASIS2z0p5K6CmgkUplOA==", + "version": "1.153.0", + "resolved": "https://registry.npmjs.org/@openui5/sap.ui.integration/-/sap.ui.integration-1.153.0.tgz", + "integrity": "sha512-2wdmZj8l0WmZ6Wwq/3aXM5pT0E6uLSXIoNod7Yaafh5PS9ngQgSHvj0+xLlznwxjQLoEYz4HvY1R3gbVKyDAGA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@openui5/sap.f": "1.152.0", - "@openui5/sap.m": "1.152.0", - "@openui5/sap.ui.core": "1.152.0", - "@openui5/sap.ui.layout": "1.152.0", - "@openui5/sap.ui.unified": "1.152.0" + "@openui5/sap.f": "1.153.0", + "@openui5/sap.m": "1.153.0", + "@openui5/sap.ui.core": "1.153.0", + "@openui5/sap.ui.layout": "1.153.0", + "@openui5/sap.ui.unified": "1.153.0" + } + }, + "node_modules/@abap2ui5/linter-render/node_modules/@openui5/sap.ui.layout": { + "version": "1.153.0", + "resolved": "https://registry.npmjs.org/@openui5/sap.ui.layout/-/sap.ui.layout-1.153.0.tgz", + "integrity": "sha512-u4nVCwbl3Xq8EGShHyUqMj/Th9B6k7Vl50kNfz+YCsEnbnk0J3zZrzuHthCB2tyu8Y2RGVaMaNqMr0h/V6qN2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@openui5/sap.ui.core": "1.153.0" + } + }, + "node_modules/@abap2ui5/linter-render/node_modules/@openui5/sap.ui.table": { + "version": "1.153.0", + "resolved": "https://registry.npmjs.org/@openui5/sap.ui.table/-/sap.ui.table-1.153.0.tgz", + "integrity": "sha512-aIjinh7r/k/cY1dyAW6SkUImJxMcvoqiiAoy3hKwtyAqQL6CfmKCt2McN7VRl3OYmYlKQ6AD/+XFiJ4T9VFcCg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@openui5/sap.ui.core": "1.153.0", + "@openui5/sap.ui.unified": "1.153.0" + } + }, + "node_modules/@abap2ui5/linter-render/node_modules/@openui5/sap.ui.unified": { + "version": "1.153.0", + "resolved": "https://registry.npmjs.org/@openui5/sap.ui.unified/-/sap.ui.unified-1.153.0.tgz", + "integrity": "sha512-m0J4zy2m7IdbTYH7U3Ce1HQ3IC0SonP2Pq6V5K1cw5m3Rur8Jc9VU7RioGHbLA1TJJYrJmhiGw3Ad9KiBROvKw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@openui5/sap.ui.core": "1.153.0" + } + }, + "node_modules/@abap2ui5/linter-render/node_modules/@openui5/sap.uxap": { + "version": "1.153.0", + "resolved": "https://registry.npmjs.org/@openui5/sap.uxap/-/sap.uxap-1.153.0.tgz", + "integrity": "sha512-ll6lBlwY0GpG4YzW1rxhfY+U9Zgh7GI6SJttzfjYPY299CJvHef+BQh9X/cx6DVi1dtlOG6ZTus38UWf4q7VQA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@openui5/sap.f": "1.153.0", + "@openui5/sap.m": "1.153.0", + "@openui5/sap.ui.core": "1.153.0", + "@openui5/sap.ui.layout": "1.153.0" } }, "node_modules/@abap2ui5/linter-render/node_modules/@openui5/themelib_sap_horizon": { - "version": "1.152.0", - "resolved": "https://registry.npmjs.org/@openui5/themelib_sap_horizon/-/themelib_sap_horizon-1.152.0.tgz", - "integrity": "sha512-NY0HkXn4fBKp3umdDVKX+D0o1Pz90hTj0+M0ri7GCj/lnHlxuLvF3lZH5hKRT/5DDx+dq9RhBNRO84EMym67AQ==", + "version": "1.153.0", + "resolved": "https://registry.npmjs.org/@openui5/themelib_sap_horizon/-/themelib_sap_horizon-1.153.0.tgz", + "integrity": "sha512-p7uwFDQvt3PMXp9GhBzPbAAhmd31kFZZ6N2cckMEyUehW1TQqNW5OQimrJwI+syM4Pnb5quz3xWPuNMdL+MxVg==", "dev": true, "license": "Apache-2.0" }, diff --git a/package.json b/package.json index 23694fcc..310312f2 100644 --- a/package.json +++ b/package.json @@ -46,8 +46,8 @@ }, "homepage": "https://github.com/abap2UI5/samples#readme", "devDependencies": { - "@abap2ui5/linter": "^0.8.5", - "@abap2ui5/linter-render": "^0.8.5", + "@abap2ui5/linter": "^0.9.0", + "@abap2ui5/linter-render": "^0.9.0", "@abaplint/cli": "^2.120.75", "@openui5/sap.f": "1.152.0", "@openui5/sap.m": "1.152.0", diff --git a/src/z2ui5_cl_smp_app_061.clas.abap b/src/z2ui5_cl_smp_app_061.clas.abap index 85dcb52d..1e6e5cac 100644 --- a/src/z2ui5_cl_smp_app_061.clas.abap +++ b/src/z2ui5_cl_smp_app_061.clas.abap @@ -63,15 +63,15 @@ CLASS z2ui5_cl_smp_app_061 IMPLEMENTATION. tab->ele( `columns` )->ele( `Column` )->tag( `Text` - )->a( n = `text` v = `uuid` + )->a( n = `text` v = `user` )->end( )->ele( `Column` )->tag( `Text` - )->a( n = `text` v = `time` + )->a( n = `text` v = `date` )->end( )->ele( `Column` )->tag( `Text` - )->a( n = `text` v = `previous` + )->a( n = `text` v = `time` )->end( ). tab->ele( `items` @@ -79,11 +79,11 @@ CLASS z2ui5_cl_smp_app_061 IMPLEMENTATION. )->a( n = `selected` v = `{SELKZ}` )->ele( `cells` )->tag( `Input` - )->a( n = `value` v = `{ID}` + )->a( n = `value` v = `{UNAME}` )->tag( `Input` - )->a( n = `value` v = `{TIMESTAMPL}` + )->a( n = `value` v = `{DATUM}` )->tag( `Input` - )->a( n = `value` v = `{ID_PREV}` ). + )->a( n = `value` v = `{UZEIT}` ). client->view_display( view->stringify( ) ). @@ -99,11 +99,10 @@ CLASS z2ui5_cl_smp_app_061 IMPLEMENTATION. IF client->check_on_init( ). " The point of this sample is a row type built at runtime from a DDIC - " name; it needs SOME table that is present on every abap2UI5 system, - " and the framework ships no RELEASED DDIC object to use instead. Reading - " the draft table is not the lesson here - the dynamic typing is. - " abap2ui5lint-disable non-released-api - DATA(row_type) = CAST cl_abap_structdescr( cl_abap_typedescr=>describe_by_name( `Z2UI5_T_01` ) ). + " name. SYST - the structure behind sy - is present on every release + " abap2UI5 runs on, ABAP Cloud included; the framework's own draft table + " is not an API (building-apps guide, section 5) and is not used here. + DATA(row_type) = CAST cl_abap_structdescr( cl_abap_typedescr=>describe_by_name( `SYST` ) ). " the DDIC components plus a SELKZ flag that exists in no dictionary: " the Table's selection binds to it, so a selected row stays selected @@ -116,12 +115,12 @@ CLASS z2ui5_cl_smp_app_061 IMPLEMENTATION. CREATE DATA t_tab TYPE HANDLE tab_type. ASSIGN t_tab->* TO . - DATA(entry) = VALUE z2ui5_t_01( id = `this is an uuid` timestampl = `20230823124303.1234567` id_prev = `previous` ). + " sy IS a SYST, so the rows are filled by component name - the only + " way to write a structure whose type exists at runtime alone DO 3 TIMES. APPEND INITIAL LINE TO ASSIGNING FIELD-SYMBOL(). - MOVE-CORRESPONDING entry TO . + MOVE-CORRESPONDING sy TO . ENDDO. - " abap2ui5lint-enable non-released-api view_display( ). diff --git a/src/z2ui5_cl_smp_app_507.clas.abap b/src/z2ui5_cl_smp_app_507.clas.abap index ba0233b5..f0c4dbb5 100644 --- a/src/z2ui5_cl_smp_app_507.clas.abap +++ b/src/z2ui5_cl_smp_app_507.clas.abap @@ -105,6 +105,7 @@ CLASS z2ui5_cl_smp_app_507 IMPLEMENTATION. render_list( parent = row title = `_bind( t_omit omit_initial = abap_true )` descr = `initial fields stay out: Design shows 5 stars - but Archived is enabled now, its abap_false was initial too` + " abap2ui5lint-disable-next-line omit-initial-drops-false -- the dropped abap_false IS the demo: the third list shows the fix items = client->_bind( val = t_omit omit_initial = abap_true ) ).