@sap/cds-dk 10.1.2 → 10.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (849) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/bin/add.js +7 -2
  3. package/bin/bind.js +0 -2
  4. package/bin/bindings.js +35 -0
  5. package/bin/build.js +11 -6
  6. package/bin/compile/index.js +1 -0
  7. package/bin/completion/index.js +10 -448
  8. package/bin/completion/scripts/cds.fish +24 -16
  9. package/bin/completion/scripts/cds.ps1 +26 -25
  10. package/bin/completion/scripts/cds.sh +22 -19
  11. package/bin/completion/scripts/cds.zsh +22 -19
  12. package/bin/deploy/index.js +1 -1
  13. package/bin/deploy/to-hana/hana.js +5 -4
  14. package/bin/env.js +0 -1
  15. package/bin/eval.js +9 -5
  16. package/bin/export.js +6 -4
  17. package/bin/help/export.md +28 -4
  18. package/bin/import.js +6 -5
  19. package/bin/inspect.js +0 -1
  20. package/bin/login.js +28 -3
  21. package/bin/repl.js +82 -26
  22. package/bin/run.js +6 -7
  23. package/bin/serve.js +6 -7
  24. package/bin/up.js +7 -2
  25. package/bin/upgrade/steps/install.js +6 -6
  26. package/bin/watch/index.js +1 -0
  27. package/lib/build/index.js +11 -7
  28. package/lib/build/plugins/featureToggles.js +2 -2
  29. package/lib/build/plugins/hana/index.js +1 -1
  30. package/lib/build/plugins/helm/files/subcharts/web-application/Chart.yaml +1 -1
  31. package/lib/build/plugins/helm/files/subcharts/web-application/templates/_helpers.tpl +7 -0
  32. package/lib/build/plugins/helm/files/subcharts/web-application/templates/api-rule.yaml +1 -0
  33. package/lib/build/plugins/helm/files/subcharts/web-application/templates/service-binding.yaml +4 -4
  34. package/lib/build/plugins/helm/files/subcharts/web-application/values.schema.json +13 -0
  35. package/lib/build/plugins/helm/files/subcharts/web-application/values.yaml +7 -1
  36. package/lib/build/plugins/java/index.js +5 -1
  37. package/lib/build/plugins/nodejs/index.js +5 -1
  38. package/lib/build/util.js +4 -5
  39. package/lib/env/schemas/cds-rc.js +5 -0
  40. package/lib/import/importapi.js +2 -3
  41. package/lib/init/constants.js +1 -1
  42. package/lib/init/index.js +8 -3
  43. package/lib/init/plugin.js +1 -1
  44. package/lib/init/projectReader.js +13 -10
  45. package/lib/init/registries/mta.js +0 -6
  46. package/lib/init/template/ai/index.js +4 -4
  47. package/lib/init/template/ams/files/extensionDeveloper.dcl +6 -0
  48. package/lib/init/template/ams/files/mta.yaml.hbs +6 -0
  49. package/lib/init/template/ams/files/sidecar.package.json.hbs +5 -0
  50. package/lib/init/template/ams/index.js +42 -40
  51. package/lib/init/template/app-frontend/files/mta.yaml.hbs +2 -0
  52. package/lib/init/template/app-frontend/files/ui5.yaml.hbs +0 -4
  53. package/lib/init/template/app-frontend/index.js +29 -24
  54. package/lib/init/template/application-logging/index.js +6 -6
  55. package/lib/init/template/approuter/files/xs-app.json.hbs +22 -0
  56. package/lib/init/template/approuter/index.js +20 -13
  57. package/lib/init/template/attachments/index.js +3 -3
  58. package/lib/init/template/audit-logging/index.js +4 -4
  59. package/lib/init/template/cloud-logging/index.js +12 -6
  60. package/lib/init/template/completion/completionSetup.js +19 -6
  61. package/lib/init/template/connectivity/index.js +3 -3
  62. package/lib/init/template/data/as-csv.js +7 -4
  63. package/lib/init/template/data/as-json.js +77 -20
  64. package/lib/init/template/destination/index.js +12 -9
  65. package/lib/init/template/dynatrace/index.js +5 -5
  66. package/lib/init/template/enterprise-messaging/index.js +6 -6
  67. package/lib/init/template/enterprise-messaging-shared/index.js +4 -4
  68. package/lib/init/template/extensibility/index.js +2 -2
  69. package/lib/init/template/extension/index.js +26 -0
  70. package/lib/init/template/github-actions/index.js +3 -3
  71. package/lib/init/template/hana/files/package.json.hbs +3 -2
  72. package/lib/init/template/hana/index.js +5 -5
  73. package/lib/init/template/hana-serverless/index.js +3 -3
  74. package/lib/init/template/html5-repo/files/mta.yaml.hbs +2 -0
  75. package/lib/init/template/html5-repo/files/ui5.yaml.hbs +0 -4
  76. package/lib/init/template/html5-repo/index.js +68 -40
  77. package/lib/init/template/http/index.js +1 -1
  78. package/lib/init/template/ias/index.js +7 -7
  79. package/lib/init/template/initial/files/.gitignore.hbs +1 -0
  80. package/lib/init/template/kafka/index.js +3 -3
  81. package/lib/init/template/kyma/index.js +7 -9
  82. package/lib/init/template/malware-scanner/index.js +3 -3
  83. package/lib/init/template/mta/index.js +6 -3
  84. package/lib/init/template/multitenancy/index.js +6 -7
  85. package/lib/init/template/notifications/index.js +2 -2
  86. package/lib/init/template/portal/index.js +16 -10
  87. package/lib/init/template/postgres/index.js +5 -5
  88. package/lib/init/template/react/files/index.html.hbs +1 -1
  89. package/lib/init/template/react/files/package.json.hbs +3 -2
  90. package/lib/init/template/react/files/src/{App.jsx.hbs → App.{{jsxExtension}}.hbs} +8 -2
  91. package/lib/init/template/react/files/src/{main.jsx → main.{{jsxExtension}}.hbs} +2 -2
  92. package/lib/init/template/react/index.js +23 -4
  93. package/lib/init/template/react/typescript/src/vite-env.d.ts +1 -0
  94. package/lib/init/template/react/typescript/tsconfig.json.hbs +16 -0
  95. package/lib/init/template/redis/index.js +2 -2
  96. package/lib/init/template/side-by-side-extensibility/index.js +6 -3
  97. package/lib/init/template/typescript/files/tsconfig.json +3 -1
  98. package/lib/init/template/vue/files/index.html.hbs +1 -1
  99. package/lib/init/template/vue/files/package.json.hbs +2 -1
  100. package/lib/init/template/vue/files/src/App.vue.hbs +8 -2
  101. package/lib/init/template/vue/index.js +20 -4
  102. package/lib/init/template/vue/typescript/tsconfig.json +11 -0
  103. package/lib/init/template/workzone-standard/files/mta.yaml.hbs +2 -2
  104. package/lib/init/template/workzone-standard/index.js +29 -27
  105. package/lib/init/template/xsuaa/files/mta.yaml.hbs +1 -1
  106. package/lib/init/template/xsuaa/files/values.yaml.hbs +1 -1
  107. package/lib/init/template/xsuaa/index.js +34 -22
  108. package/lib/mtx/auth_manager.js +8 -2
  109. package/lib/mtx/browser_login.js +181 -0
  110. package/lib/mtx/params.js +6 -0
  111. package/lib/mtx/settings_manager.js +29 -4
  112. package/lib/util/cf.js +44 -8
  113. package/lib/util/fs.js +2 -2
  114. package/node_modules/@cap-js/db-service/CHANGELOG.md +10 -0
  115. package/node_modules/@cap-js/db-service/lib/cqn2pql.js +4 -0
  116. package/node_modules/@cap-js/db-service/lib/cqn2sql.js +3 -0
  117. package/node_modules/@cap-js/db-service/lib/cqn4sql.js +8 -23
  118. package/node_modules/@cap-js/db-service/lib/infer/index.js +20 -27
  119. package/node_modules/@cap-js/db-service/package.json +1 -1
  120. package/node_modules/@cap-js/openapi/cds-plugin.js +12 -0
  121. package/node_modules/@cap-js/openapi/index.js +3 -1
  122. package/node_modules/@cap-js/openapi/lib/compile/csdl2openapi.js +652 -413
  123. package/node_modules/@cap-js/openapi/lib/compile/diagram.js +16 -13
  124. package/node_modules/@cap-js/openapi/lib/compile/index.js +10 -7
  125. package/node_modules/@cap-js/openapi/lib/compile/property-util.js +51 -0
  126. package/{lib/import/openapi → node_modules/@cap-js/openapi/lib/import}/importOpenAPI.js +12 -9
  127. package/{lib/import/openapi → node_modules/@cap-js/openapi/lib/import}/index.js +4 -3
  128. package/node_modules/@cap-js/openapi/package.json +71 -3
  129. package/node_modules/@cap-js/sqlite/CHANGELOG.md +9 -0
  130. package/node_modules/@cap-js/sqlite/package.json +3 -3
  131. package/node_modules/@isaacs/fs-minipass/LICENSE +15 -0
  132. package/node_modules/@isaacs/fs-minipass/README.md +71 -0
  133. package/node_modules/@isaacs/fs-minipass/dist/commonjs/index.d.ts +118 -0
  134. package/node_modules/@isaacs/fs-minipass/dist/commonjs/index.d.ts.map +1 -0
  135. package/node_modules/@isaacs/fs-minipass/dist/commonjs/index.js +430 -0
  136. package/node_modules/@isaacs/fs-minipass/dist/commonjs/index.js.map +1 -0
  137. package/node_modules/@isaacs/fs-minipass/dist/commonjs/package.json +3 -0
  138. package/node_modules/@isaacs/fs-minipass/dist/esm/index.d.ts +118 -0
  139. package/node_modules/@isaacs/fs-minipass/dist/esm/index.d.ts.map +1 -0
  140. package/node_modules/@isaacs/fs-minipass/dist/esm/index.js +420 -0
  141. package/node_modules/@isaacs/fs-minipass/dist/esm/index.js.map +1 -0
  142. package/node_modules/@isaacs/fs-minipass/dist/esm/package.json +3 -0
  143. package/node_modules/@isaacs/fs-minipass/package.json +72 -0
  144. package/node_modules/@sap/cds/CHANGELOG.md +52 -1
  145. package/node_modules/@sap/cds/_i18n/messages_ar.properties +1 -0
  146. package/node_modules/@sap/cds/_i18n/messages_bg.properties +1 -0
  147. package/node_modules/@sap/cds/_i18n/messages_cs.properties +1 -0
  148. package/node_modules/@sap/cds/_i18n/messages_da.properties +1 -0
  149. package/node_modules/@sap/cds/_i18n/messages_de.properties +1 -0
  150. package/node_modules/@sap/cds/_i18n/messages_el.properties +1 -0
  151. package/node_modules/@sap/cds/_i18n/messages_en.properties +1 -0
  152. package/node_modules/@sap/cds/_i18n/messages_es.properties +1 -0
  153. package/node_modules/@sap/cds/_i18n/messages_es_MX.properties +1 -0
  154. package/node_modules/@sap/cds/_i18n/messages_fi.properties +1 -0
  155. package/node_modules/@sap/cds/_i18n/messages_fr.properties +1 -0
  156. package/node_modules/@sap/cds/_i18n/messages_he.properties +1 -0
  157. package/node_modules/@sap/cds/_i18n/messages_hr.properties +1 -0
  158. package/node_modules/@sap/cds/_i18n/messages_hu.properties +1 -0
  159. package/node_modules/@sap/cds/_i18n/messages_it.properties +1 -0
  160. package/node_modules/@sap/cds/_i18n/messages_ja.properties +1 -0
  161. package/node_modules/@sap/cds/_i18n/messages_kk.properties +1 -0
  162. package/node_modules/@sap/cds/_i18n/messages_ko.properties +1 -0
  163. package/node_modules/@sap/cds/_i18n/messages_ms.properties +1 -0
  164. package/node_modules/@sap/cds/_i18n/messages_nl.properties +1 -0
  165. package/node_modules/@sap/cds/_i18n/messages_no.properties +1 -0
  166. package/node_modules/@sap/cds/_i18n/messages_pl.properties +1 -0
  167. package/node_modules/@sap/cds/_i18n/messages_pt.properties +1 -0
  168. package/node_modules/@sap/cds/_i18n/messages_ro.properties +1 -0
  169. package/node_modules/@sap/cds/_i18n/messages_ru.properties +1 -0
  170. package/node_modules/@sap/cds/_i18n/messages_sh.properties +1 -0
  171. package/node_modules/@sap/cds/_i18n/messages_sk.properties +1 -0
  172. package/node_modules/@sap/cds/_i18n/messages_sl.properties +1 -0
  173. package/node_modules/@sap/cds/_i18n/messages_sv.properties +1 -0
  174. package/node_modules/@sap/cds/_i18n/messages_th.properties +1 -0
  175. package/node_modules/@sap/cds/_i18n/messages_tr.properties +1 -0
  176. package/node_modules/@sap/cds/_i18n/messages_uk.properties +1 -0
  177. package/node_modules/@sap/cds/_i18n/messages_vi.properties +1 -0
  178. package/node_modules/@sap/cds/_i18n/messages_zh_CN.properties +1 -0
  179. package/node_modules/@sap/cds/_i18n/messages_zh_TW.properties +1 -0
  180. package/node_modules/@sap/cds/app/index-client.js +164 -0
  181. package/node_modules/@sap/cds/app/index.css +598 -87
  182. package/node_modules/@sap/cds/app/index.html +54 -30
  183. package/node_modules/@sap/cds/app/index.js +311 -67
  184. package/node_modules/@sap/cds/app/table.html +226 -0
  185. package/node_modules/@sap/cds/app/table.js +302 -0
  186. package/node_modules/@sap/cds/bin/serve.js +3 -2
  187. package/node_modules/@sap/cds/eslint.config.mjs +2 -0
  188. package/node_modules/@sap/cds/lib/compile/cdsc.js +7 -0
  189. package/node_modules/@sap/cds/lib/compile/for/embeddings.js +27 -0
  190. package/node_modules/@sap/cds/lib/compile/load.js +2 -2
  191. package/node_modules/@sap/cds/lib/compile/minify.js +17 -4
  192. package/node_modules/@sap/cds/lib/compile/parse.js +3 -0
  193. package/node_modules/@sap/cds/lib/compile/resolve.js +16 -14
  194. package/node_modules/@sap/cds/lib/core/classes.js +1 -0
  195. package/node_modules/@sap/cds/lib/dbs/cds-deploy.js +4 -5
  196. package/node_modules/@sap/cds/lib/env/cds-env.js +132 -70
  197. package/node_modules/@sap/cds/lib/env/cds-requires/auth-strategies.js +62 -0
  198. package/node_modules/@sap/cds/lib/env/cds-requires/databases.js +49 -0
  199. package/node_modules/@sap/cds/lib/env/cds-requires/embeddings.js +8 -0
  200. package/node_modules/@sap/cds/lib/env/cds-requires/index.js +27 -0
  201. package/node_modules/@sap/cds/lib/env/cds-requires/messaging.js +82 -0
  202. package/node_modules/@sap/cds/lib/env/cds-requires/platform.js +23 -0
  203. package/node_modules/@sap/cds/lib/env/cds-requires/queues.js +34 -0
  204. package/node_modules/@sap/cds/lib/env/cds-requires/services.js +32 -0
  205. package/node_modules/@sap/cds/lib/env/defaults.js +9 -1
  206. package/node_modules/@sap/cds/lib/i18n/files.js +4 -4
  207. package/node_modules/@sap/cds/lib/i18n/locale.js +1 -1
  208. package/node_modules/@sap/cds/lib/index.js +9 -9
  209. package/node_modules/@sap/cds/lib/log/cds-log.js +3 -3
  210. package/node_modules/@sap/cds/lib/ql/SELECT.js +2 -0
  211. package/node_modules/@sap/cds/lib/ql/UPDATE.js +1 -1
  212. package/node_modules/@sap/cds/lib/ql/cds.ql-Query.js +4 -1
  213. package/node_modules/@sap/cds/lib/ql/core/@types/cqn.d.ts +146 -0
  214. package/node_modules/@sap/cds/lib/ql/core/@types/exprs.d.ts +51 -0
  215. package/node_modules/@sap/cds/lib/ql/core/@types/index.d.ts +29 -0
  216. package/node_modules/@sap/cds/lib/ql/core/@types/package.json +7 -0
  217. package/node_modules/@sap/cds/lib/ql/core/@types/ql/delete.d.ts +8 -0
  218. package/node_modules/@sap/cds/lib/ql/core/@types/ql/insert.d.ts +19 -0
  219. package/node_modules/@sap/cds/lib/ql/core/@types/ql/select.d.ts +24 -0
  220. package/node_modules/@sap/cds/lib/ql/core/@types/ql/update.d.ts +10 -0
  221. package/node_modules/@sap/cds/lib/ql/core/@types/query.d.ts +18 -0
  222. package/node_modules/@sap/cds/lib/ql/core/cql/parser.min.js +1 -0
  223. package/node_modules/@sap/cds/lib/ql/core/lib/index.js +69 -0
  224. package/node_modules/@sap/cds/lib/ql/core/lib/ql/cache.js +34 -0
  225. package/node_modules/@sap/cds/lib/ql/core/lib/ql/call-action.js +6 -0
  226. package/node_modules/@sap/cds/lib/ql/core/lib/ql/delete.js +8 -0
  227. package/node_modules/@sap/cds/lib/ql/core/lib/ql/insert.js +26 -0
  228. package/node_modules/@sap/cds/lib/ql/core/lib/ql/select.js +22 -0
  229. package/node_modules/@sap/cds/lib/ql/core/lib/ql/update.js +26 -0
  230. package/node_modules/@sap/cds/lib/ql/core/lib/query.js +85 -0
  231. package/node_modules/@sap/cds/lib/ql/core/lib/xl/fluent.js +47 -0
  232. package/node_modules/@sap/cds/lib/ql/core/lib/xl/ttl.js +24 -0
  233. package/node_modules/@sap/cds/lib/ql/core/license +201 -0
  234. package/node_modules/@sap/cds/lib/ql/core/package.json +24 -0
  235. package/node_modules/@sap/cds/lib/ql/core/readme.md +99 -0
  236. package/node_modules/@sap/cds/lib/ql/core/upstream.json +5 -0
  237. package/node_modules/@sap/cds/lib/req/spawn.js +1 -1
  238. package/node_modules/@sap/cds/lib/srv/bindings.js +111 -115
  239. package/node_modules/@sap/cds/lib/srv/cds-connect.js +11 -10
  240. package/node_modules/@sap/cds/lib/srv/cds-serve.js +16 -7
  241. package/node_modules/@sap/cds/lib/srv/cds.Service.js +13 -7
  242. package/node_modules/@sap/cds/lib/srv/factory.js +8 -10
  243. package/node_modules/@sap/cds/lib/srv/middlewares/auth/ias-auth.js +35 -32
  244. package/node_modules/@sap/cds/lib/srv/middlewares/auth/jwt-auth.js +5 -1
  245. package/node_modules/@sap/cds/lib/srv/middlewares/auth/mocked-users.js +1 -1
  246. package/node_modules/@sap/cds/lib/srv/protocols/hcql.js +230 -79
  247. package/node_modules/@sap/cds/lib/srv/protocols/http.js +7 -3
  248. package/node_modules/@sap/cds/lib/srv/protocols/index.js +7 -2
  249. package/node_modules/@sap/cds/lib/srv/srv-dispatch.js +2 -2
  250. package/node_modules/@sap/cds/lib/utils/cds-utils.js +37 -0
  251. package/node_modules/@sap/cds/lib/utils/csv-reader.js +2 -2
  252. package/node_modules/@sap/cds/libx/_runtime/common/generic/assert.js +18 -27
  253. package/node_modules/@sap/cds/libx/_runtime/common/generic/crud.js +1 -1
  254. package/node_modules/@sap/cds/libx/_runtime/common/utils/rewriteAsterisks.js +1 -1
  255. package/node_modules/@sap/cds/libx/_runtime/fiori/lean-draft.js +121 -84
  256. package/node_modules/@sap/cds/libx/_runtime/messaging/common-utils/authorizedRequest.js +24 -1
  257. package/node_modules/@sap/cds/libx/_runtime/remote/Service.js +2 -2
  258. package/node_modules/@sap/cds/libx/_runtime/remote/utils/client.js +3 -2
  259. package/node_modules/@sap/cds/libx/_runtime/remote/utils/query.js +11 -6
  260. package/node_modules/@sap/cds/libx/odata/middleware/create.js +4 -0
  261. package/node_modules/@sap/cds/libx/odata/middleware/metadata.js +1 -1
  262. package/node_modules/@sap/cds/libx/odata/middleware/operation.js +3 -0
  263. package/node_modules/@sap/cds/libx/odata/middleware/parse.js +9 -0
  264. package/node_modules/@sap/cds/libx/odata/middleware/read.js +6 -0
  265. package/node_modules/@sap/cds/libx/odata/middleware/update.js +5 -1
  266. package/node_modules/@sap/cds/libx/odata/parse/afterburner.js +3 -3
  267. package/node_modules/@sap/cds/libx/odata/parse/multipartToJson.js +1 -1
  268. package/node_modules/@sap/cds/libx/odata/utils/ieee754.js +20 -0
  269. package/node_modules/@sap/cds/libx/queue/api.js +1 -1
  270. package/node_modules/@sap/cds/libx/queue/index.js +3 -1
  271. package/node_modules/@sap/cds/libx/queue/processing.js +5 -0
  272. package/node_modules/@sap/cds/libx/rest/RestAdapter.js +1 -0
  273. package/node_modules/@sap/cds/package.json +2 -2
  274. package/node_modules/@sap/cds/server.js +1 -0
  275. package/node_modules/@sap/cds/srv/ucl-service.cds +1 -0
  276. package/node_modules/@sap/cds-compiler/CHANGELOG.md +83 -0
  277. package/node_modules/@sap/cds-compiler/bin/cdsse.js +1 -1
  278. package/node_modules/@sap/cds-compiler/doc/EffectiveCSN.md +3314 -0
  279. package/node_modules/@sap/cds-compiler/lib/api/main.js +9 -6
  280. package/node_modules/@sap/cds-compiler/lib/api/options.js +3 -3
  281. package/node_modules/@sap/cds-compiler/lib/{model → base}/csnUtils.js +5 -5
  282. package/node_modules/@sap/cds-compiler/lib/base/message-registry.js +54 -6
  283. package/node_modules/@sap/cds-compiler/lib/base/optionProcessor.js +4 -4
  284. package/node_modules/@sap/cds-compiler/lib/{model → base}/sortViews.js +1 -1
  285. package/node_modules/@sap/cds-compiler/lib/checks/assocOutsideService.js +1 -1
  286. package/node_modules/@sap/cds-compiler/lib/checks/checkForTypes.js +1 -1
  287. package/node_modules/@sap/cds-compiler/lib/checks/checkPathsInStoredCalcElement.js +1 -1
  288. package/node_modules/@sap/cds-compiler/lib/checks/elements.js +37 -3
  289. package/node_modules/@sap/cds-compiler/lib/checks/enricher.js +1 -1
  290. package/node_modules/@sap/cds-compiler/lib/checks/existsInForbiddenPlaces.js +1 -1
  291. package/node_modules/@sap/cds-compiler/lib/checks/hasPersistedElements.js +1 -1
  292. package/node_modules/@sap/cds-compiler/lib/checks/manyExpand.js +1 -1
  293. package/node_modules/@sap/cds-compiler/lib/checks/manyNavigations.js +1 -1
  294. package/node_modules/@sap/cds-compiler/lib/checks/onConditions.js +1 -1
  295. package/node_modules/@sap/cds-compiler/lib/checks/parameters.js +1 -1
  296. package/node_modules/@sap/cds-compiler/lib/checks/queryNoDbArtifacts.js +1 -1
  297. package/node_modules/@sap/cds-compiler/lib/checks/selectItems.js +1 -1
  298. package/node_modules/@sap/cds-compiler/lib/checks/structuredAnnoExpressions.js +1 -1
  299. package/node_modules/@sap/cds-compiler/lib/checks/typeParameters.js +1 -1
  300. package/node_modules/@sap/cds-compiler/lib/checks/types.js +1 -1
  301. package/node_modules/@sap/cds-compiler/lib/checks/validator.js +1 -1
  302. package/node_modules/@sap/cds-compiler/lib/compiler/assert-consistency.js +20 -12
  303. package/node_modules/@sap/cds-compiler/lib/compiler/builtins.js +9 -4
  304. package/node_modules/@sap/cds-compiler/lib/compiler/checks.js +50 -0
  305. package/node_modules/@sap/cds-compiler/lib/compiler/define.js +303 -323
  306. package/node_modules/@sap/cds-compiler/lib/compiler/dictionaries.js +5 -0
  307. package/node_modules/@sap/cds-compiler/lib/compiler/extend.js +1015 -1177
  308. package/node_modules/@sap/cds-compiler/lib/compiler/generate.js +55 -42
  309. package/node_modules/@sap/cds-compiler/lib/compiler/populate.js +74 -45
  310. package/node_modules/@sap/cds-compiler/lib/compiler/propagator.js +1 -0
  311. package/node_modules/@sap/cds-compiler/lib/compiler/resolve.js +6 -4
  312. package/node_modules/@sap/cds-compiler/lib/compiler/shared.js +30 -49
  313. package/node_modules/@sap/cds-compiler/lib/compiler/utils.js +32 -18
  314. package/node_modules/@sap/cds-compiler/lib/edm/annotations/edmJson.js +3 -3
  315. package/node_modules/@sap/cds-compiler/lib/edm/annotations/genericTranslation.js +2 -2
  316. package/node_modules/@sap/cds-compiler/lib/edm/annotations/preprocessAnnotations.js +2 -3
  317. package/node_modules/@sap/cds-compiler/lib/edm/csn2edm.js +1 -1
  318. package/node_modules/@sap/cds-compiler/lib/edm/edm.js +6 -7
  319. package/node_modules/@sap/cds-compiler/lib/edm/edmAnnoPreprocessor.js +1 -1
  320. package/node_modules/@sap/cds-compiler/lib/edm/edmInboundChecks.js +1 -1
  321. package/node_modules/@sap/cds-compiler/lib/edm/edmPreprocessor.js +1 -1
  322. package/node_modules/@sap/cds-compiler/lib/edm/edmUtils.js +12 -7
  323. package/node_modules/@sap/cds-compiler/lib/gen/CdlGrammar.checksum +1 -1
  324. package/node_modules/@sap/cds-compiler/lib/gen/CdlParser.js +15 -15
  325. package/node_modules/@sap/cds-compiler/lib/gen/Dictionary.json +7 -0
  326. package/node_modules/@sap/cds-compiler/lib/json/from-csn.js +30 -30
  327. package/node_modules/@sap/cds-compiler/lib/json/to-csn.js +2 -1
  328. package/node_modules/@sap/cds-compiler/lib/main.js +4 -1
  329. package/node_modules/@sap/cds-compiler/lib/parsers/AstBuildingParser.js +42 -15
  330. package/node_modules/@sap/cds-compiler/lib/render/DuplicateChecker.js +37 -11
  331. package/node_modules/@sap/cds-compiler/lib/render/manageConstraints.js +1 -1
  332. package/node_modules/@sap/cds-compiler/lib/render/toCdl.js +11 -6
  333. package/node_modules/@sap/cds-compiler/lib/render/toRename.js +1 -1
  334. package/node_modules/@sap/cds-compiler/lib/render/toSql.js +74 -24
  335. package/node_modules/@sap/cds-compiler/lib/render/utils/common.js +1 -1
  336. package/node_modules/@sap/cds-compiler/lib/render/utils/operators.js +81 -0
  337. package/node_modules/@sap/cds-compiler/lib/render/utils/sql.js +17 -10
  338. package/node_modules/@sap/cds-compiler/lib/transform/db/assertUnique.js +1 -1
  339. package/node_modules/@sap/cds-compiler/lib/transform/db/associations.js +3 -4
  340. package/node_modules/@sap/cds-compiler/lib/transform/db/assocsToQueries/transformExists.js +1 -1
  341. package/node_modules/@sap/cds-compiler/lib/transform/db/backlinks.js +2 -2
  342. package/node_modules/@sap/cds-compiler/lib/transform/db/cdsPersistence.js +1 -1
  343. package/node_modules/@sap/cds-compiler/lib/transform/db/constraints.js +6 -5
  344. package/node_modules/@sap/cds-compiler/lib/transform/db/expansion.js +7 -1
  345. package/node_modules/@sap/cds-compiler/lib/transform/db/flattening.js +2 -2
  346. package/node_modules/@sap/cds-compiler/lib/{modelCompare/compare.js → transform/db/migration/diffModels.js} +5 -5
  347. package/node_modules/@sap/cds-compiler/lib/{modelCompare/utils/filter.js → transform/db/migration/filterDiff.js} +2 -2
  348. package/node_modules/@sap/cds-compiler/lib/transform/db/processSqlServices.js +1 -1
  349. package/node_modules/@sap/cds-compiler/lib/transform/db/rewriteCalculatedElements.js +1 -1
  350. package/node_modules/@sap/cds-compiler/lib/transform/db/temporal.js +1 -1
  351. package/node_modules/@sap/cds-compiler/lib/transform/db/views.js +2 -6
  352. package/node_modules/@sap/cds-compiler/lib/transform/draft/db.js +1 -1
  353. package/node_modules/@sap/cds-compiler/lib/transform/draft/odata.js +1 -1
  354. package/node_modules/@sap/cds-compiler/lib/transform/effective/annotations.js +1 -1
  355. package/node_modules/@sap/cds-compiler/lib/transform/effective/associations.js +1 -1
  356. package/node_modules/@sap/cds-compiler/lib/transform/effective/flattening.js +1 -1
  357. package/node_modules/@sap/cds-compiler/lib/transform/effective/main.js +3 -2
  358. package/node_modules/@sap/cds-compiler/lib/transform/effective/misc.js +2 -1
  359. package/node_modules/@sap/cds-compiler/lib/transform/effective/queries.js +1 -1
  360. package/node_modules/@sap/cds-compiler/lib/transform/effective/types.js +1 -1
  361. package/node_modules/@sap/cds-compiler/lib/transform/forOdata.js +1 -1
  362. package/node_modules/@sap/cds-compiler/lib/transform/forRelationalDB.js +9 -4
  363. package/node_modules/@sap/cds-compiler/lib/transform/localized.js +1 -1
  364. package/node_modules/@sap/cds-compiler/lib/transform/odata/adaptAnnotationRefs.js +5 -11
  365. package/node_modules/@sap/cds-compiler/lib/transform/odata/createForeignKeys.js +1 -1
  366. package/node_modules/@sap/cds-compiler/lib/transform/odata/flattening.js +4 -4
  367. package/node_modules/@sap/cds-compiler/lib/transform/odata/foreignKeyRefsInXprAnnos.js +5 -3
  368. package/node_modules/@sap/cds-compiler/lib/transform/odata/toFinalBaseType.js +29 -5
  369. package/node_modules/@sap/cds-compiler/lib/transform/odata/typesExposure.js +13 -3
  370. package/node_modules/@sap/cds-compiler/lib/transform/odata/utils.js +9 -0
  371. package/node_modules/@sap/cds-compiler/lib/transform/transformUtils.js +2 -2
  372. package/node_modules/@sap/cds-compiler/lib/transform/translateAssocsToJoins.js +1 -1
  373. package/node_modules/@sap/cds-compiler/lib/transform/tupleExpansion.js +1 -1
  374. package/node_modules/@sap/cds-compiler/lib/transform/universalCsn/coreComputed.js +1 -1
  375. package/node_modules/@sap/cds-compiler/lib/transform/universalCsn/universalCsnEnricher.js +1 -1
  376. package/node_modules/@sap/cds-compiler/lib/transform/universalCsn/utils.js +1 -1
  377. package/node_modules/@sap/cds-compiler/package.json +1 -1
  378. package/node_modules/@sap/cds-mtxs/CHANGELOG.md +47 -0
  379. package/node_modules/@sap/cds-mtxs/bin/cds-mtx-migrate.js +4 -6
  380. package/node_modules/@sap/cds-mtxs/bin/cds-mtx.js +5 -4
  381. package/node_modules/@sap/cds-mtxs/cds-plugin.js +38 -2
  382. package/node_modules/@sap/cds-mtxs/db/t0.cds +7 -0
  383. package/node_modules/@sap/cds-mtxs/lib/utils.js +129 -20
  384. package/node_modules/@sap/cds-mtxs/package.json +15 -14
  385. package/node_modules/@sap/cds-mtxs/srv/cf/abstract-provisioning-service.js +13 -12
  386. package/node_modules/@sap/cds-mtxs/srv/cf/saas-provisioning-service.cds +1 -0
  387. package/node_modules/@sap/cds-mtxs/srv/cf/sms-provisioning-service.cds +1 -0
  388. package/node_modules/@sap/cds-mtxs/srv/extensibility/compat/update.js +5 -2
  389. package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/config.js +1 -2
  390. package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/csv-allowlist.js +64 -0
  391. package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/index.js +4 -2
  392. package/node_modules/@sap/cds-mtxs/srv/extensibility/linter/protected-namespace.js +67 -5
  393. package/node_modules/@sap/cds-mtxs/srv/extensibility-service.js +179 -15
  394. package/node_modules/@sap/cds-mtxs/srv/jobs-service.js +12 -3
  395. package/node_modules/@sap/cds-mtxs/srv/plugins/common.js +33 -12
  396. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/ctnr-mgr-base.js +24 -6
  397. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/hdi-ctnr-mgr.js +3 -1
  398. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/hdi-native.js +752 -0
  399. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/serverless.js +17 -20
  400. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/srv-mgr-v2.js +511 -0
  401. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/srv-mgr.js +11 -4
  402. package/node_modules/@sap/cds-mtxs/srv/plugins/hana/tms.js +8 -0
  403. package/node_modules/@sap/cds-mtxs/srv/plugins/hana.js +27 -18
  404. package/node_modules/@sap/cds-mtxs/srv/worker/job-worker-pool.js +1 -1
  405. package/node_modules/@sap/cds-mtxs/srv/worker/job-worker.js +1 -1
  406. package/node_modules/chownr/LICENSE.md +63 -0
  407. package/node_modules/chownr/README.md +3 -0
  408. package/node_modules/chownr/dist/commonjs/index.d.ts +3 -0
  409. package/node_modules/chownr/dist/commonjs/index.d.ts.map +1 -0
  410. package/node_modules/chownr/dist/commonjs/index.js +93 -0
  411. package/node_modules/chownr/dist/commonjs/index.js.map +1 -0
  412. package/node_modules/chownr/dist/commonjs/package.json +3 -0
  413. package/node_modules/chownr/dist/esm/index.d.ts +3 -0
  414. package/node_modules/chownr/dist/esm/index.d.ts.map +1 -0
  415. package/node_modules/chownr/dist/esm/index.js +85 -0
  416. package/node_modules/chownr/dist/esm/index.js.map +1 -0
  417. package/node_modules/chownr/dist/esm/package.json +3 -0
  418. package/node_modules/chownr/package.json +69 -0
  419. package/node_modules/content-disposition/README.md +105 -35
  420. package/node_modules/content-disposition/dist/index.d.ts +72 -0
  421. package/node_modules/content-disposition/dist/index.js +388 -0
  422. package/node_modules/content-disposition/dist/index.js.map +1 -0
  423. package/node_modules/content-disposition/package.json +31 -19
  424. package/node_modules/content-type/README.md +34 -57
  425. package/node_modules/content-type/package.json +35 -25
  426. package/node_modules/express/Readme.md +15 -9
  427. package/node_modules/express/lib/application.js +2 -2
  428. package/node_modules/express/lib/request.js +32 -19
  429. package/node_modules/express/lib/response.js +27 -30
  430. package/node_modules/express/package.json +10 -10
  431. package/node_modules/handlebars/bin/handlebars +1 -1
  432. package/node_modules/handlebars/dist/amd/handlebars/base.js +2 -2
  433. package/node_modules/handlebars/dist/amd/handlebars/compiler/base.js +2 -59
  434. package/node_modules/handlebars/dist/amd/handlebars/compiler/code-gen.js +68 -5
  435. package/node_modules/handlebars/dist/amd/handlebars/compiler/compiler.js +160 -19
  436. package/node_modules/handlebars/dist/amd/handlebars/compiler/javascript-compiler.js +23 -7
  437. package/node_modules/handlebars/dist/amd/handlebars/compiler/node-types.js +12 -0
  438. package/node_modules/handlebars/dist/amd/handlebars/compiler/visitor.js +26 -7
  439. package/node_modules/handlebars/dist/amd/handlebars/compiler/whitespace-control.js +9 -4
  440. package/node_modules/handlebars/dist/amd/handlebars/exception.js +8 -4
  441. package/node_modules/handlebars/dist/amd/handlebars/helpers/each.js +40 -14
  442. package/node_modules/handlebars/dist/amd/handlebars/internal/proto-access.js +21 -1
  443. package/node_modules/handlebars/dist/amd/handlebars/runtime.js +24 -4
  444. package/node_modules/handlebars/dist/amd/handlebars/utils.js +4 -3
  445. package/node_modules/handlebars/dist/amd/precompiler.js +13 -7
  446. package/node_modules/handlebars/dist/cjs/handlebars/base.js +2 -2
  447. package/node_modules/handlebars/dist/cjs/handlebars/compiler/base.js +1 -60
  448. package/node_modules/handlebars/dist/cjs/handlebars/compiler/code-gen.js +64 -4
  449. package/node_modules/handlebars/dist/cjs/handlebars/compiler/compiler.js +161 -18
  450. package/node_modules/handlebars/dist/cjs/handlebars/compiler/javascript-compiler.js +23 -7
  451. package/node_modules/handlebars/dist/cjs/handlebars/compiler/node-types.js +10 -0
  452. package/node_modules/handlebars/dist/cjs/handlebars/compiler/visitor.js +29 -6
  453. package/node_modules/handlebars/dist/cjs/handlebars/compiler/whitespace-control.js +9 -4
  454. package/node_modules/handlebars/dist/cjs/handlebars/exception.js +8 -4
  455. package/node_modules/handlebars/dist/cjs/handlebars/helpers/each.js +40 -14
  456. package/node_modules/handlebars/dist/cjs/handlebars/internal/proto-access.js +21 -1
  457. package/node_modules/handlebars/dist/cjs/handlebars/runtime.js +24 -4
  458. package/node_modules/handlebars/dist/cjs/handlebars/utils.js +4 -3
  459. package/node_modules/handlebars/dist/cjs/precompiler.js +14 -6
  460. package/node_modules/handlebars/dist/handlebars.amd.js +401 -130
  461. package/node_modules/handlebars/dist/handlebars.amd.min.js +4 -4
  462. package/node_modules/handlebars/dist/handlebars.js +396 -125
  463. package/node_modules/handlebars/dist/handlebars.min.js +4 -4
  464. package/node_modules/handlebars/dist/handlebars.runtime.amd.js +100 -29
  465. package/node_modules/handlebars/dist/handlebars.runtime.amd.min.js +2 -2
  466. package/node_modules/handlebars/dist/handlebars.runtime.js +94 -23
  467. package/node_modules/handlebars/dist/handlebars.runtime.min.js +2 -2
  468. package/node_modules/handlebars/lib/handlebars/base.js +1 -1
  469. package/node_modules/handlebars/lib/handlebars/compiler/base.js +0 -67
  470. package/node_modules/handlebars/lib/handlebars/compiler/code-gen.js +65 -11
  471. package/node_modules/handlebars/lib/handlebars/compiler/compiler.js +164 -23
  472. package/node_modules/handlebars/lib/handlebars/compiler/javascript-compiler.js +23 -7
  473. package/node_modules/handlebars/lib/handlebars/compiler/node-types.js +24 -0
  474. package/node_modules/handlebars/lib/handlebars/compiler/visitor.js +29 -5
  475. package/node_modules/handlebars/lib/handlebars/compiler/whitespace-control.js +16 -5
  476. package/node_modules/handlebars/lib/handlebars/exception.js +7 -3
  477. package/node_modules/handlebars/lib/handlebars/helpers/each.js +39 -16
  478. package/node_modules/handlebars/lib/handlebars/internal/proto-access.js +22 -0
  479. package/node_modules/handlebars/lib/handlebars/runtime.js +36 -4
  480. package/node_modules/handlebars/lib/handlebars/utils.js +3 -2
  481. package/node_modules/handlebars/lib/precompiler.js +14 -5
  482. package/node_modules/handlebars/package.json +2 -2
  483. package/node_modules/handlebars/release-notes.md +20 -1
  484. package/node_modules/handlebars/types/index.d.ts +8 -0
  485. package/node_modules/hdb/cfg/VERSION +1 -1
  486. package/node_modules/hdb/lib/Client.js +6 -2
  487. package/node_modules/hdb/lib/protocol/ClientInfo.js +28 -15
  488. package/node_modules/hdb/lib/protocol/Connection.js +30 -3
  489. package/node_modules/hdb/lib/protocol/Writer.js +2 -2
  490. package/node_modules/hdb/lib/protocol/common/ConnectOption.js +2 -0
  491. package/node_modules/hdb/lib/protocol/common/ConnectOptionFlagSet1.js +18 -0
  492. package/node_modules/hdb/lib/protocol/common/ConnectOptionType.js +2 -0
  493. package/node_modules/hdb/lib/protocol/common/Constants.js +1 -0
  494. package/node_modules/hdb/lib/protocol/common/MessageType.js +3 -2
  495. package/node_modules/hdb/lib/protocol/common/PartKind.js +2 -1
  496. package/node_modules/hdb/lib/protocol/common/index.js +1 -0
  497. package/node_modules/hdb/lib/protocol/data/TextList.js +25 -17
  498. package/node_modules/hdb/lib/protocol/data/index.js +1 -0
  499. package/node_modules/hdb/lib/protocol/part/ConnectOptions.js +7 -0
  500. package/node_modules/hdb/lib/protocol/request/index.js +7 -0
  501. package/node_modules/hdb/package.json +1 -2
  502. package/node_modules/livereload-js/.github/workflows/main.yml +4 -4
  503. package/node_modules/livereload-js/README.md +3 -3
  504. package/node_modules/livereload-js/dist/livereload.js +839 -2742
  505. package/node_modules/livereload-js/dist/livereload.min.js +1 -1
  506. package/node_modules/livereload-js/package.json +11 -11
  507. package/node_modules/minipass/LICENSE.md +55 -0
  508. package/node_modules/minipass/README.md +825 -0
  509. package/node_modules/minipass/dist/commonjs/index.d.ts +545 -0
  510. package/node_modules/minipass/dist/commonjs/index.d.ts.map +1 -0
  511. package/node_modules/minipass/dist/commonjs/index.js +1038 -0
  512. package/node_modules/minipass/dist/commonjs/index.js.map +1 -0
  513. package/node_modules/minipass/dist/commonjs/package.json +3 -0
  514. package/node_modules/minipass/dist/esm/index.d.ts +545 -0
  515. package/node_modules/minipass/dist/esm/index.d.ts.map +1 -0
  516. package/node_modules/minipass/dist/esm/index.js +1020 -0
  517. package/node_modules/minipass/dist/esm/index.js.map +1 -0
  518. package/node_modules/minipass/dist/esm/package.json +3 -0
  519. package/node_modules/minipass/package.json +77 -0
  520. package/node_modules/minizlib/LICENSE +26 -0
  521. package/node_modules/minizlib/README.md +64 -0
  522. package/node_modules/minizlib/dist/commonjs/constants.d.ts +2 -0
  523. package/node_modules/minizlib/dist/commonjs/constants.d.ts.map +1 -0
  524. package/node_modules/minizlib/dist/commonjs/constants.js +123 -0
  525. package/node_modules/minizlib/dist/commonjs/constants.js.map +1 -0
  526. package/node_modules/minizlib/dist/commonjs/index.d.ts +99 -0
  527. package/node_modules/minizlib/dist/commonjs/index.d.ts.map +1 -0
  528. package/node_modules/minizlib/dist/commonjs/index.js +416 -0
  529. package/node_modules/minizlib/dist/commonjs/index.js.map +1 -0
  530. package/node_modules/minizlib/dist/commonjs/package.json +3 -0
  531. package/node_modules/minizlib/dist/esm/constants.d.ts +2 -0
  532. package/node_modules/minizlib/dist/esm/constants.d.ts.map +1 -0
  533. package/node_modules/minizlib/dist/esm/constants.js +117 -0
  534. package/node_modules/minizlib/dist/esm/constants.js.map +1 -0
  535. package/node_modules/minizlib/dist/esm/index.d.ts +99 -0
  536. package/node_modules/minizlib/dist/esm/index.d.ts.map +1 -0
  537. package/node_modules/minizlib/dist/esm/index.js +363 -0
  538. package/node_modules/minizlib/dist/esm/index.js.map +1 -0
  539. package/node_modules/minizlib/dist/esm/package.json +3 -0
  540. package/node_modules/minizlib/package.json +80 -0
  541. package/node_modules/qs/.github/THREAT_MODEL.md +4 -2
  542. package/node_modules/qs/CHANGELOG.md +38 -14
  543. package/node_modules/qs/README.md +31 -3
  544. package/node_modules/qs/dist/qs.js +20 -20
  545. package/node_modules/qs/lib/parse.js +94 -4
  546. package/node_modules/qs/lib/stringify.js +4 -4
  547. package/node_modules/qs/lib/utils.js +130 -6
  548. package/node_modules/qs/package.json +4 -4
  549. package/node_modules/qs/test/parse.js +174 -0
  550. package/node_modules/qs/test/stringify.js +263 -33
  551. package/node_modules/qs/test/utils.js +184 -0
  552. package/node_modules/tar/LICENSE.md +55 -0
  553. package/node_modules/tar/README.md +1233 -0
  554. package/node_modules/tar/dist/commonjs/create.d.ts +3 -0
  555. package/node_modules/tar/dist/commonjs/create.d.ts.map +1 -0
  556. package/node_modules/tar/dist/commonjs/create.js +82 -0
  557. package/node_modules/tar/dist/commonjs/create.js.map +1 -0
  558. package/node_modules/tar/dist/commonjs/cwd-error.d.ts +8 -0
  559. package/node_modules/tar/dist/commonjs/cwd-error.d.ts.map +1 -0
  560. package/node_modules/tar/dist/commonjs/cwd-error.js +18 -0
  561. package/node_modules/tar/dist/commonjs/cwd-error.js.map +1 -0
  562. package/node_modules/tar/dist/commonjs/extract.d.ts +3 -0
  563. package/node_modules/tar/dist/commonjs/extract.d.ts.map +1 -0
  564. package/node_modules/tar/dist/commonjs/extract.js +88 -0
  565. package/node_modules/tar/dist/commonjs/extract.js.map +1 -0
  566. package/node_modules/tar/dist/commonjs/get-write-flag.d.ts +2 -0
  567. package/node_modules/tar/dist/commonjs/get-write-flag.d.ts.map +1 -0
  568. package/node_modules/tar/dist/commonjs/get-write-flag.js +32 -0
  569. package/node_modules/tar/dist/commonjs/get-write-flag.js.map +1 -0
  570. package/node_modules/tar/dist/commonjs/header.d.ts +53 -0
  571. package/node_modules/tar/dist/commonjs/header.d.ts.map +1 -0
  572. package/node_modules/tar/dist/commonjs/header.js +348 -0
  573. package/node_modules/tar/dist/commonjs/header.js.map +1 -0
  574. package/node_modules/tar/dist/commonjs/index.d.ts +20 -0
  575. package/node_modules/tar/dist/commonjs/index.d.ts.map +1 -0
  576. package/node_modules/tar/dist/commonjs/index.js +64 -0
  577. package/node_modules/tar/dist/commonjs/index.js.map +1 -0
  578. package/node_modules/tar/dist/commonjs/index.min.js +4 -0
  579. package/node_modules/tar/dist/commonjs/index.min.js.map +7 -0
  580. package/node_modules/tar/dist/commonjs/large-numbers.d.ts +3 -0
  581. package/node_modules/tar/dist/commonjs/large-numbers.d.ts.map +1 -0
  582. package/node_modules/tar/dist/commonjs/large-numbers.js +99 -0
  583. package/node_modules/tar/dist/commonjs/large-numbers.js.map +1 -0
  584. package/node_modules/tar/dist/commonjs/list.d.ts +7 -0
  585. package/node_modules/tar/dist/commonjs/list.d.ts.map +1 -0
  586. package/node_modules/tar/dist/commonjs/list.js +153 -0
  587. package/node_modules/tar/dist/commonjs/list.js.map +1 -0
  588. package/node_modules/tar/dist/commonjs/make-command.d.ts +49 -0
  589. package/node_modules/tar/dist/commonjs/make-command.d.ts.map +1 -0
  590. package/node_modules/tar/dist/commonjs/make-command.js +52 -0
  591. package/node_modules/tar/dist/commonjs/make-command.js.map +1 -0
  592. package/node_modules/tar/dist/commonjs/mkdir.d.ts +25 -0
  593. package/node_modules/tar/dist/commonjs/mkdir.d.ts.map +1 -0
  594. package/node_modules/tar/dist/commonjs/mkdir.js +187 -0
  595. package/node_modules/tar/dist/commonjs/mkdir.js.map +1 -0
  596. package/node_modules/tar/dist/commonjs/mode-fix.d.ts +2 -0
  597. package/node_modules/tar/dist/commonjs/mode-fix.d.ts.map +1 -0
  598. package/node_modules/tar/dist/commonjs/mode-fix.js +29 -0
  599. package/node_modules/tar/dist/commonjs/mode-fix.js.map +1 -0
  600. package/node_modules/tar/dist/commonjs/normalize-unicode.d.ts +2 -0
  601. package/node_modules/tar/dist/commonjs/normalize-unicode.d.ts.map +1 -0
  602. package/node_modules/tar/dist/commonjs/normalize-unicode.js +38 -0
  603. package/node_modules/tar/dist/commonjs/normalize-unicode.js.map +1 -0
  604. package/node_modules/tar/dist/commonjs/normalize-windows-path.d.ts +2 -0
  605. package/node_modules/tar/dist/commonjs/normalize-windows-path.d.ts.map +1 -0
  606. package/node_modules/tar/dist/commonjs/normalize-windows-path.js +12 -0
  607. package/node_modules/tar/dist/commonjs/normalize-windows-path.js.map +1 -0
  608. package/node_modules/tar/dist/commonjs/options.d.ts +604 -0
  609. package/node_modules/tar/dist/commonjs/options.d.ts.map +1 -0
  610. package/node_modules/tar/dist/commonjs/options.js +66 -0
  611. package/node_modules/tar/dist/commonjs/options.js.map +1 -0
  612. package/node_modules/tar/dist/commonjs/pack.d.ts +105 -0
  613. package/node_modules/tar/dist/commonjs/pack.d.ts.map +1 -0
  614. package/node_modules/tar/dist/commonjs/pack.js +544 -0
  615. package/node_modules/tar/dist/commonjs/pack.js.map +1 -0
  616. package/node_modules/tar/dist/commonjs/package.json +3 -0
  617. package/node_modules/tar/dist/commonjs/parse.d.ts +92 -0
  618. package/node_modules/tar/dist/commonjs/parse.d.ts.map +1 -0
  619. package/node_modules/tar/dist/commonjs/parse.js +655 -0
  620. package/node_modules/tar/dist/commonjs/parse.js.map +1 -0
  621. package/node_modules/tar/dist/commonjs/path-reservations.d.ts +11 -0
  622. package/node_modules/tar/dist/commonjs/path-reservations.d.ts.map +1 -0
  623. package/node_modules/tar/dist/commonjs/path-reservations.js +170 -0
  624. package/node_modules/tar/dist/commonjs/path-reservations.js.map +1 -0
  625. package/node_modules/tar/dist/commonjs/pax.d.ts +26 -0
  626. package/node_modules/tar/dist/commonjs/pax.d.ts.map +1 -0
  627. package/node_modules/tar/dist/commonjs/pax.js +182 -0
  628. package/node_modules/tar/dist/commonjs/pax.js.map +1 -0
  629. package/node_modules/tar/dist/commonjs/process-umask.d.ts +2 -0
  630. package/node_modules/tar/dist/commonjs/process-umask.d.ts.map +1 -0
  631. package/node_modules/tar/dist/commonjs/process-umask.js +7 -0
  632. package/node_modules/tar/dist/commonjs/process-umask.js.map +1 -0
  633. package/node_modules/tar/dist/commonjs/read-entry.d.ts +36 -0
  634. package/node_modules/tar/dist/commonjs/read-entry.d.ts.map +1 -0
  635. package/node_modules/tar/dist/commonjs/read-entry.js +136 -0
  636. package/node_modules/tar/dist/commonjs/read-entry.js.map +1 -0
  637. package/node_modules/tar/dist/commonjs/replace.d.ts +2 -0
  638. package/node_modules/tar/dist/commonjs/replace.d.ts.map +1 -0
  639. package/node_modules/tar/dist/commonjs/replace.js +227 -0
  640. package/node_modules/tar/dist/commonjs/replace.js.map +1 -0
  641. package/node_modules/tar/dist/commonjs/strip-absolute-path.d.ts +2 -0
  642. package/node_modules/tar/dist/commonjs/strip-absolute-path.d.ts.map +1 -0
  643. package/node_modules/tar/dist/commonjs/strip-absolute-path.js +29 -0
  644. package/node_modules/tar/dist/commonjs/strip-absolute-path.js.map +1 -0
  645. package/node_modules/tar/dist/commonjs/strip-trailing-slashes.d.ts +2 -0
  646. package/node_modules/tar/dist/commonjs/strip-trailing-slashes.d.ts.map +1 -0
  647. package/node_modules/tar/dist/commonjs/strip-trailing-slashes.js +18 -0
  648. package/node_modules/tar/dist/commonjs/strip-trailing-slashes.js.map +1 -0
  649. package/node_modules/tar/dist/commonjs/symlink-error.d.ts +9 -0
  650. package/node_modules/tar/dist/commonjs/symlink-error.d.ts.map +1 -0
  651. package/node_modules/tar/dist/commonjs/symlink-error.js +19 -0
  652. package/node_modules/tar/dist/commonjs/symlink-error.js.map +1 -0
  653. package/node_modules/tar/dist/commonjs/types.d.ts +16 -0
  654. package/node_modules/tar/dist/commonjs/types.d.ts.map +1 -0
  655. package/node_modules/tar/dist/commonjs/types.js +70 -0
  656. package/node_modules/tar/dist/commonjs/types.js.map +1 -0
  657. package/node_modules/tar/dist/commonjs/unpack.d.ts +101 -0
  658. package/node_modules/tar/dist/commonjs/unpack.d.ts.map +1 -0
  659. package/node_modules/tar/dist/commonjs/unpack.js +932 -0
  660. package/node_modules/tar/dist/commonjs/unpack.js.map +1 -0
  661. package/node_modules/tar/dist/commonjs/update.d.ts +2 -0
  662. package/node_modules/tar/dist/commonjs/update.d.ts.map +1 -0
  663. package/node_modules/tar/dist/commonjs/update.js +33 -0
  664. package/node_modules/tar/dist/commonjs/update.js.map +1 -0
  665. package/node_modules/tar/dist/commonjs/warn-method.d.ts +24 -0
  666. package/node_modules/tar/dist/commonjs/warn-method.d.ts.map +1 -0
  667. package/node_modules/tar/dist/commonjs/warn-method.js +31 -0
  668. package/node_modules/tar/dist/commonjs/warn-method.js.map +1 -0
  669. package/node_modules/tar/dist/commonjs/winchars.d.ts +3 -0
  670. package/node_modules/tar/dist/commonjs/winchars.d.ts.map +1 -0
  671. package/node_modules/tar/dist/commonjs/winchars.js +14 -0
  672. package/node_modules/tar/dist/commonjs/winchars.js.map +1 -0
  673. package/node_modules/tar/dist/commonjs/write-entry.d.ts +129 -0
  674. package/node_modules/tar/dist/commonjs/write-entry.d.ts.map +1 -0
  675. package/node_modules/tar/dist/commonjs/write-entry.js +698 -0
  676. package/node_modules/tar/dist/commonjs/write-entry.js.map +1 -0
  677. package/node_modules/tar/dist/esm/create.d.ts +3 -0
  678. package/node_modules/tar/dist/esm/create.d.ts.map +1 -0
  679. package/node_modules/tar/dist/esm/create.js +76 -0
  680. package/node_modules/tar/dist/esm/create.js.map +1 -0
  681. package/node_modules/tar/dist/esm/cwd-error.d.ts +8 -0
  682. package/node_modules/tar/dist/esm/cwd-error.d.ts.map +1 -0
  683. package/node_modules/tar/dist/esm/cwd-error.js +14 -0
  684. package/node_modules/tar/dist/esm/cwd-error.js.map +1 -0
  685. package/node_modules/tar/dist/esm/extract.d.ts +3 -0
  686. package/node_modules/tar/dist/esm/extract.d.ts.map +1 -0
  687. package/node_modules/tar/dist/esm/extract.js +49 -0
  688. package/node_modules/tar/dist/esm/extract.js.map +1 -0
  689. package/node_modules/tar/dist/esm/get-write-flag.d.ts +2 -0
  690. package/node_modules/tar/dist/esm/get-write-flag.d.ts.map +1 -0
  691. package/node_modules/tar/dist/esm/get-write-flag.js +26 -0
  692. package/node_modules/tar/dist/esm/get-write-flag.js.map +1 -0
  693. package/node_modules/tar/dist/esm/header.d.ts +53 -0
  694. package/node_modules/tar/dist/esm/header.d.ts.map +1 -0
  695. package/node_modules/tar/dist/esm/header.js +311 -0
  696. package/node_modules/tar/dist/esm/header.js.map +1 -0
  697. package/node_modules/tar/dist/esm/index.d.ts +20 -0
  698. package/node_modules/tar/dist/esm/index.d.ts.map +1 -0
  699. package/node_modules/tar/dist/esm/index.js +20 -0
  700. package/node_modules/tar/dist/esm/index.js.map +1 -0
  701. package/node_modules/tar/dist/esm/index.min.js +4 -0
  702. package/node_modules/tar/dist/esm/index.min.js.map +7 -0
  703. package/node_modules/tar/dist/esm/large-numbers.d.ts +3 -0
  704. package/node_modules/tar/dist/esm/large-numbers.d.ts.map +1 -0
  705. package/node_modules/tar/dist/esm/large-numbers.js +94 -0
  706. package/node_modules/tar/dist/esm/large-numbers.js.map +1 -0
  707. package/node_modules/tar/dist/esm/list.d.ts +7 -0
  708. package/node_modules/tar/dist/esm/list.d.ts.map +1 -0
  709. package/node_modules/tar/dist/esm/list.js +113 -0
  710. package/node_modules/tar/dist/esm/list.js.map +1 -0
  711. package/node_modules/tar/dist/esm/make-command.d.ts +49 -0
  712. package/node_modules/tar/dist/esm/make-command.d.ts.map +1 -0
  713. package/node_modules/tar/dist/esm/make-command.js +48 -0
  714. package/node_modules/tar/dist/esm/make-command.js.map +1 -0
  715. package/node_modules/tar/dist/esm/mkdir.d.ts +25 -0
  716. package/node_modules/tar/dist/esm/mkdir.d.ts.map +1 -0
  717. package/node_modules/tar/dist/esm/mkdir.js +179 -0
  718. package/node_modules/tar/dist/esm/mkdir.js.map +1 -0
  719. package/node_modules/tar/dist/esm/mode-fix.d.ts +2 -0
  720. package/node_modules/tar/dist/esm/mode-fix.d.ts.map +1 -0
  721. package/node_modules/tar/dist/esm/mode-fix.js +25 -0
  722. package/node_modules/tar/dist/esm/mode-fix.js.map +1 -0
  723. package/node_modules/tar/dist/esm/normalize-unicode.d.ts +2 -0
  724. package/node_modules/tar/dist/esm/normalize-unicode.d.ts.map +1 -0
  725. package/node_modules/tar/dist/esm/normalize-unicode.js +34 -0
  726. package/node_modules/tar/dist/esm/normalize-unicode.js.map +1 -0
  727. package/node_modules/tar/dist/esm/normalize-windows-path.d.ts +2 -0
  728. package/node_modules/tar/dist/esm/normalize-windows-path.d.ts.map +1 -0
  729. package/node_modules/tar/dist/esm/normalize-windows-path.js +9 -0
  730. package/node_modules/tar/dist/esm/normalize-windows-path.js.map +1 -0
  731. package/node_modules/tar/dist/esm/options.d.ts +604 -0
  732. package/node_modules/tar/dist/esm/options.d.ts.map +1 -0
  733. package/node_modules/tar/dist/esm/options.js +54 -0
  734. package/node_modules/tar/dist/esm/options.js.map +1 -0
  735. package/node_modules/tar/dist/esm/pack.d.ts +105 -0
  736. package/node_modules/tar/dist/esm/pack.d.ts.map +1 -0
  737. package/node_modules/tar/dist/esm/pack.js +502 -0
  738. package/node_modules/tar/dist/esm/pack.js.map +1 -0
  739. package/node_modules/tar/dist/esm/package.json +3 -0
  740. package/node_modules/tar/dist/esm/parse.d.ts +92 -0
  741. package/node_modules/tar/dist/esm/parse.d.ts.map +1 -0
  742. package/node_modules/tar/dist/esm/parse.js +651 -0
  743. package/node_modules/tar/dist/esm/parse.js.map +1 -0
  744. package/node_modules/tar/dist/esm/path-reservations.d.ts +11 -0
  745. package/node_modules/tar/dist/esm/path-reservations.d.ts.map +1 -0
  746. package/node_modules/tar/dist/esm/path-reservations.js +166 -0
  747. package/node_modules/tar/dist/esm/path-reservations.js.map +1 -0
  748. package/node_modules/tar/dist/esm/pax.d.ts +26 -0
  749. package/node_modules/tar/dist/esm/pax.d.ts.map +1 -0
  750. package/node_modules/tar/dist/esm/pax.js +178 -0
  751. package/node_modules/tar/dist/esm/pax.js.map +1 -0
  752. package/node_modules/tar/dist/esm/process-umask.d.ts +2 -0
  753. package/node_modules/tar/dist/esm/process-umask.d.ts.map +1 -0
  754. package/node_modules/tar/dist/esm/process-umask.js +3 -0
  755. package/node_modules/tar/dist/esm/process-umask.js.map +1 -0
  756. package/node_modules/tar/dist/esm/read-entry.d.ts +36 -0
  757. package/node_modules/tar/dist/esm/read-entry.d.ts.map +1 -0
  758. package/node_modules/tar/dist/esm/read-entry.js +132 -0
  759. package/node_modules/tar/dist/esm/read-entry.js.map +1 -0
  760. package/node_modules/tar/dist/esm/replace.d.ts +2 -0
  761. package/node_modules/tar/dist/esm/replace.d.ts.map +1 -0
  762. package/node_modules/tar/dist/esm/replace.js +221 -0
  763. package/node_modules/tar/dist/esm/replace.js.map +1 -0
  764. package/node_modules/tar/dist/esm/strip-absolute-path.d.ts +2 -0
  765. package/node_modules/tar/dist/esm/strip-absolute-path.d.ts.map +1 -0
  766. package/node_modules/tar/dist/esm/strip-absolute-path.js +25 -0
  767. package/node_modules/tar/dist/esm/strip-absolute-path.js.map +1 -0
  768. package/node_modules/tar/dist/esm/strip-trailing-slashes.d.ts +2 -0
  769. package/node_modules/tar/dist/esm/strip-trailing-slashes.d.ts.map +1 -0
  770. package/node_modules/tar/dist/esm/strip-trailing-slashes.js +14 -0
  771. package/node_modules/tar/dist/esm/strip-trailing-slashes.js.map +1 -0
  772. package/node_modules/tar/dist/esm/symlink-error.d.ts +9 -0
  773. package/node_modules/tar/dist/esm/symlink-error.d.ts.map +1 -0
  774. package/node_modules/tar/dist/esm/symlink-error.js +15 -0
  775. package/node_modules/tar/dist/esm/symlink-error.js.map +1 -0
  776. package/node_modules/tar/dist/esm/types.d.ts +16 -0
  777. package/node_modules/tar/dist/esm/types.d.ts.map +1 -0
  778. package/node_modules/tar/dist/esm/types.js +65 -0
  779. package/node_modules/tar/dist/esm/types.js.map +1 -0
  780. package/node_modules/tar/dist/esm/unpack.d.ts +101 -0
  781. package/node_modules/tar/dist/esm/unpack.d.ts.map +1 -0
  782. package/node_modules/tar/dist/esm/unpack.js +891 -0
  783. package/node_modules/tar/dist/esm/unpack.js.map +1 -0
  784. package/node_modules/tar/dist/esm/update.d.ts +2 -0
  785. package/node_modules/tar/dist/esm/update.d.ts.map +1 -0
  786. package/node_modules/tar/dist/esm/update.js +30 -0
  787. package/node_modules/tar/dist/esm/update.js.map +1 -0
  788. package/node_modules/tar/dist/esm/warn-method.d.ts +24 -0
  789. package/node_modules/tar/dist/esm/warn-method.d.ts.map +1 -0
  790. package/node_modules/tar/dist/esm/warn-method.js +27 -0
  791. package/node_modules/tar/dist/esm/warn-method.js.map +1 -0
  792. package/node_modules/tar/dist/esm/winchars.d.ts +3 -0
  793. package/node_modules/tar/dist/esm/winchars.d.ts.map +1 -0
  794. package/node_modules/tar/dist/esm/winchars.js +9 -0
  795. package/node_modules/tar/dist/esm/winchars.js.map +1 -0
  796. package/node_modules/tar/dist/esm/write-entry.d.ts +129 -0
  797. package/node_modules/tar/dist/esm/write-entry.d.ts.map +1 -0
  798. package/node_modules/tar/dist/esm/write-entry.js +656 -0
  799. package/node_modules/tar/dist/esm/write-entry.js.map +1 -0
  800. package/node_modules/tar/package.json +298 -0
  801. package/node_modules/ws/lib/websocket.js +17 -3
  802. package/node_modules/ws/package.json +1 -1
  803. package/node_modules/yallist/LICENSE.md +63 -0
  804. package/node_modules/yallist/README.md +205 -0
  805. package/node_modules/yallist/dist/commonjs/index.d.ts +39 -0
  806. package/node_modules/yallist/dist/commonjs/index.d.ts.map +1 -0
  807. package/node_modules/yallist/dist/commonjs/index.js +384 -0
  808. package/node_modules/yallist/dist/commonjs/index.js.map +1 -0
  809. package/node_modules/yallist/dist/commonjs/package.json +3 -0
  810. package/node_modules/yallist/dist/esm/index.d.ts +39 -0
  811. package/node_modules/yallist/dist/esm/index.d.ts.map +1 -0
  812. package/node_modules/yallist/dist/esm/index.js +379 -0
  813. package/node_modules/yallist/dist/esm/index.js.map +1 -0
  814. package/node_modules/yallist/dist/esm/package.json +3 -0
  815. package/node_modules/yallist/package.json +68 -0
  816. package/package.json +7 -1
  817. package/bin/completion/templates/cds-tmpl.fish +0 -65
  818. package/bin/completion/templates/cds-tmpl.ps1 +0 -217
  819. package/bin/completion/templates/cds-tmpl.sh +0 -93
  820. package/bin/completion/templates/cds-tmpl.zsh +0 -74
  821. package/node_modules/@cap-js/db-service/lib/recursion-guard.js +0 -40
  822. package/node_modules/@sap/cds/lib/env/cds-requires.js +0 -327
  823. package/node_modules/@sap/cds-mtxs/srv/bootstrap.cds +0 -2
  824. package/node_modules/@sap/cds-mtxs/srv/bootstrap.js +0 -33
  825. package/node_modules/body-parser/node_modules/content-type/LICENSE +0 -22
  826. package/node_modules/body-parser/node_modules/content-type/README.md +0 -71
  827. package/node_modules/body-parser/node_modules/content-type/package.json +0 -52
  828. package/node_modules/content-disposition/index.js +0 -536
  829. package/node_modules/content-type/HISTORY.md +0 -29
  830. package/node_modules/content-type/index.js +0 -225
  831. package/node_modules/negotiator/node_modules/content-type/LICENSE +0 -22
  832. package/node_modules/negotiator/node_modules/content-type/README.md +0 -71
  833. package/node_modules/negotiator/node_modules/content-type/dist/index.d.ts +0 -46
  834. package/node_modules/negotiator/node_modules/content-type/dist/index.js +0 -176
  835. package/node_modules/negotiator/node_modules/content-type/dist/index.js.map +0 -1
  836. package/node_modules/negotiator/node_modules/content-type/package.json +0 -52
  837. package/node_modules/type-is/node_modules/content-type/LICENSE +0 -22
  838. package/node_modules/type-is/node_modules/content-type/README.md +0 -71
  839. package/node_modules/type-is/node_modules/content-type/dist/index.d.ts +0 -46
  840. package/node_modules/type-is/node_modules/content-type/dist/index.js +0 -176
  841. package/node_modules/type-is/node_modules/content-type/dist/index.js.map +0 -1
  842. package/node_modules/type-is/node_modules/content-type/package.json +0 -52
  843. /package/lib/init/template/react/files/{vite.config.js.hbs → vite.config.{{extension}}.hbs} +0 -0
  844. /package/lib/init/template/vue/files/src/{main.js → main.{{extension}}.hbs} +0 -0
  845. /package/lib/init/template/vue/files/{vite.config.js.hbs → vite.config.{{extension}}.hbs} +0 -0
  846. /package/{lib/import/openapi → node_modules/@cap-js/openapi/lib/import}/utilities.js +0 -0
  847. /package/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.d.ts +0 -0
  848. /package/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.js +0 -0
  849. /package/node_modules/{body-parser/node_modules/content-type → content-type}/dist/index.js.map +0 -0
@@ -1,11 +1,51 @@
1
- // Extend
1
+ // Provide functions for extensions and includes
2
+
3
+ // The main functions are the following, the first three are called on-demand in
4
+ // the "origin chain loop", i.e. in dependency order:
5
+ //
6
+ // extendArtifactBefore(), called at the start of the loop body:
7
+ // - traverses collected extensions for the given artifact, and for each property,
8
+ // select one (or sort them, e.g. for `includes`) if multiple extensions exist
9
+ // - _also called_ by main function of this file for all user-defined main artifacts,
10
+ // because we need some annotations rather early → the "origin" is not necessarily
11
+ // processed → this fn can't inspect the "origin" or derived props of includes
12
+ //
13
+ // … in between: populateGeneratedEntity(), resolveInclude(), populateArtifact()
14
+ //
15
+ // extendArtifactAdd(), called in the middle of the loop body:
16
+ // - add elements, enums and actions to artifact via includes and/or extension
17
+ //
18
+ // … in between: set _effectiveType, mergeSpecifiedElementsOrEnum(), generateForEntity()
19
+ //
20
+ // extendArtifactAfter(), called at the end of the loop body:
21
+ // - pushes down member extensions to members
22
+ // - handles type property extensions (TODO: move to extendArtifactAdd)
23
+ //
24
+ // createRemainingAnnotateStatements(), called near end of compilation
25
+ // - creates `annotate` statements for non-applied extensions
26
+
27
+ // Sections in this file: -------------------------------------------------------
28
+ // - Pushdown and transform extensions
29
+ // - Sort sources, select/sort extension
30
+ // - Array annotations with `...`, same anno values
31
+ // - Special properties: query clauses, type properties
32
+ // - Add new members
33
+ // - Create “super” ANNOTATE statements
34
+ // - TODO TMP: initMembers()
35
+ // - TODO TMP: includes
36
+ // - Foreign key extensions (currently postponed)
37
+ // - Utility functions
2
38
 
3
39
  'use strict';
4
40
 
5
41
  const { weakRefLocation } = require('../base/location');
6
- const { searchName } = require('../base/messages');
7
- const { dictAdd, pushToDict, dictForEach } = require('./dictionaries');
8
- const { kindProperties, dictKinds } = require('./base');
42
+ const {
43
+ dictAdd,
44
+ pushToDict,
45
+ dictNonEmpty,
46
+ dictFirst,
47
+ } = require('./dictionaries');
48
+ const { kindProperties } = require('./base');
9
49
  const {
10
50
  setLink,
11
51
  setArtifactLink,
@@ -13,9 +53,8 @@ const {
13
53
  setExpandStatus,
14
54
  linkToOrigin,
15
55
  initItemsLinks,
16
- setMemberParent,
56
+ outerArtifact,
17
57
  createAndLinkCalcDepElement,
18
- initExprAnnoBlock,
19
58
  initBoundSelfParam,
20
59
  dependsOnSilent,
21
60
  hasSecurityAnno,
@@ -26,13 +65,12 @@ const {
26
65
  forEachDefinition,
27
66
  forEachMember,
28
67
  forEachGeneric,
29
- isDirectComposition,
30
- targetCantBeAspect,
31
68
  } = require('./utils');
32
69
  const layers = require('./moduleLayers');
33
70
  const { CompilerAssertion } = require('../base/error');
34
71
  const { Location } = require('../base/location');
35
72
  const { typeParameters } = require('./builtins');
73
+ const { XsnArtifact, XsnName } = require('./xsn-model');
36
74
 
37
75
  const $location = Symbol.for( 'cds.$location' );
38
76
  const $inferred = Symbol.for( 'cds.$inferred' ); // TODO: no $inferred yet?
@@ -53,10 +91,6 @@ const draftBoundActions = [
53
91
  'draftEdit',
54
92
  ];
55
93
 
56
- function canBeDraftMember( name, parent, draftMembers ) {
57
- return parent?.kind === 'entity' && parent._service && draftMembers.includes( name );
58
- }
59
-
60
94
  function extend( model ) {
61
95
  // Get simplified "resolve" functionality and the message function:
62
96
  const {
@@ -68,7 +102,6 @@ function extend( model ) {
68
102
  resolveTypeArgumentsUnchecked,
69
103
  resolveDefinitionName,
70
104
  attachAndEmitValidNames,
71
- checkRedefinition,
72
105
  } = model.$functions;
73
106
 
74
107
  Object.assign( model.$functions, {
@@ -78,117 +111,15 @@ function extend( model ) {
78
111
  extendArtifactAdd,
79
112
  extendForeignKeys,
80
113
  withLocalizedData,
81
- applyIncludes, // TODO: re-check
82
114
  } );
83
115
 
84
- const includeCollisions = [];
85
-
86
- forEachGeneric( model, 'definitions', tagCompositionTargets );
87
- dictForEach( model.$collectedExtensions, e => e._extensions.forEach( tagCompositionTargets ) );
88
- // remark: tagging on extensions works _before_ running extendArtifactBefore() on each artifact
89
116
  sortModelSources();
90
-
91
117
  // Set annotations on user-provided artifacts, but they are not propagated yet!
92
- // Use them in the main compiler phase (and before) with extra care:
93
118
  forEachDefinition( model, extendArtifactBefore );
94
119
  return;
95
120
 
96
- // Tag composition targets: ---------------------------------------------------
97
-
98
- function tagCompositionTargets( elem ) {
99
- if (elem.$inferred) // TODO: probably no $inferred yet
100
- return;
101
- if (elem.targetAspect?.elements)
102
- elem = elem.targetAspect;
103
- if (elem.elements) {
104
- forEachGeneric( elem, 'elements', tagCompositionTargets );
105
- }
106
- else if (elem.columns) { // `elem` is query or extension
107
- elem.columns.forEach( tagCompositionTargets );
108
- }
109
- else if (elem.$queries) {
110
- for (const query of elem.$queries) {
111
- if (query.mixin)
112
- forEachGeneric( query, 'mixin', tagCompositionTargets );
113
- if (query.columns)
114
- query.columns.forEach( tagCompositionTargets );
115
- // Remark: no directly published expand/inline column yet
116
- }
117
- }
118
- else if (elem.target && isDirectComposition( elem )) {
119
- const name = resolveUncheckedPath( elem.target, 'target', elem );
120
- if (!name)
121
- return;
122
- const target = model.definitions[name];
123
- // move target aspect in `target` to `targetAspect` (in define.js, we only
124
- // do it with anonymous aspect)
125
- if (target?.kind in { aspect: 1, type: 1 } && // type is sloppy
126
- target.elements && !target.elements[$inferred] &&
127
- !targetCantBeAspect( elem, false, model.definitions )) { // tests `!elem.targetAspect`
128
- elem.targetAspect = elem.target;
129
- delete elem.target;
130
- }
131
- model.$compositionTargets[name] = true; // does not hurt if set on aspect
132
- }
133
- }
134
-
135
-
136
- //-----------------------------------------------------------------------------
137
- // Extensions: general algorithm
138
- //-----------------------------------------------------------------------------
139
- // extendArtifactBefore, extendArtifactAfter, createRemainingAnnotateStatements,
140
- // extendForeignKeys
141
-
142
- /**
143
- * Goes through all (applied) annotations in the given artifact and chooses one
144
- * if multiple exist according to the module layer.
145
- * TODO: update comment if extension algorithm is finished
146
- *
147
- * Called at the beginning for each main artifact, and must not call
148
- * resolvePath() then. It is later called via effectiveType().
149
- *
150
- * @param {XSN.Artifact} art
151
- */
152
- function extendArtifactBefore( art ) {
153
- // for main artifacts, move extensions from `$collectedExtensions` model dictionary:
154
- if (!art._main && !art._outer && art._extensions === undefined &&
155
- art.name && // TODO: probably just a workaround, check with TODO in getOriginRaw()
156
- art.kind !== 'namespace') {
157
- const { id } = art.name;
158
- setLink( art, '_extensions', model.$collectedExtensions[id]?._extensions || null );
159
- if (art._extensions && !art.builtin) { // keep extensions for builtin in $collectedExtensions
160
- delete model.$collectedExtensions[id];
161
- // TODO: if the extension mechanism has been completed, we could uncomment:
162
- // art._extensions.forEach( ext => resolvePath( ext.name, ext.kind, ext )); // for LSP
163
- // for now, we do that at the end of createRemainingAnnotateStatements()
164
- }
165
- }
166
- if (art.kind === 'entity' && art.includes && !art._entityIncludes)
167
- setEntityIncludes( art, art );
168
121
 
169
- if (art._extensions) {
170
- // TODO: the following function can now be simplified
171
- // if (art.$inferred) console.log('CAI:', art.name, art.$inferred,art._extensions)
172
- // With extensions, member appears in CSN, affects directly the rendering of
173
- // elements etc. TODO: do that more specifically on the dicts (via symbol)
174
- // Probably better: we could use the _extensions dict prop directly in to-csn
175
- if (art.$inferred)
176
- setExpandStatus( art, 'annotate' );
177
- if (Array.isArray( art._extensions )) {
178
- checkExtensionsKind( art._extensions, art );
179
- transformArtifactExtensions( art );
180
- }
181
- // console.log('EA:',require('../model/revealInternalProperties')
182
- // .ref(art),Object.keys(art._extensions))
183
- for (const prop in art._extensions) {
184
- if (Object.hasOwn( art._extensions, prop ) &&
185
- // remark: if we change the array, consider whether to delete the artifact
186
- // TODO: what is the `$gen`? `$add` is handled...
187
- ![ 'elements', 'actions', 'params', '$gen' ].includes( prop ))
188
- applyPropertyExtensions( art, prop );
189
- }
190
- }
191
- }
122
+ // Pushdown and transform extensions ------------------------------------------
192
123
 
193
124
  /**
194
125
  * Push down extensions on member properties like `elements` to the individual
@@ -240,14 +171,17 @@ function extend( model ) {
240
171
  annotateFor( art, 'params', '' ); // create anno for non-existing returns
241
172
  for (const ext of extensionsMap.elements) {
242
173
  if (!ext.returns) {
174
+ if (artProp === 'returns') {
175
+ reportMissingReturns( ext, art );
176
+ if (ext.kind === 'extend')
177
+ continue;
178
+ }
243
179
  pushToDict( returnsDict || art[artProp], '_extensions', ext );
244
- if (artProp === 'returns')
245
- extendHandleReturns( ext, art );
246
180
  }
247
181
  else {
248
182
  pushToDict( returnsDict || art[artProp], '_extensions', ext.returns );
249
183
  if (!art.returns)
250
- checkReturnsExtension( ext, art );
184
+ reportUnexpectedReturns( ext, art );
251
185
  }
252
186
  }
253
187
  // TODO: what about `many many Type` (via CSN)?
@@ -255,7 +189,7 @@ function extend( model ) {
255
189
  else if (!art.target) { // TODO: foreign keys currently handled specially
256
190
  for (const ext of extensionsMap.elements) {
257
191
  if (ext.returns)
258
- checkReturnsExtension( ext, art );
192
+ reportUnexpectedReturns( ext, art ); // TODO: ???
259
193
  }
260
194
  // if (art.elements || art.enum || art.kind === 'annotate')
261
195
  moveDictExtensions( art, extensionsMap,
@@ -263,114 +197,26 @@ function extend( model ) {
263
197
  }
264
198
  }
265
199
 
266
- /**
267
- * Apply foreign key extensions. Because foreign keys are handled late in the compiler
268
- * (in tweak-assocs.js), we can't apply them in effectiveType(), yet.
269
- * Instead, we postpone applying them until all foreign keys were generated.
270
- *
271
- * @param art
272
- */
273
- function extendForeignKeys( art ) {
274
- // See extendArtifactAfter() for targetAspect/items handling.
275
- if (!art._extensions || art.items || art.targetAspect?.elements)
276
- return;
277
-
278
- // push down foreign keys
279
- moveDictExtensions( art, art._extensions, 'foreignKeys', 'elements' );
280
- if (!art.foreignKeys)
281
- return;
282
-
283
- forEachGeneric(art, 'foreignKeys', (key) => {
284
- if (!key._effectiveType)
285
- throw new CompilerAssertion('foreign key should have been processed');
286
- extendArtifactBefore( key );
287
- extendArtifactAfter( key );
288
- });
289
- }
290
-
291
- /**
292
- * Applying extensions is handled in extendArtifactAfter(). And only afterward,
293
- * an effective sequence number is set. Meaning that if a sub artifact already
294
- * has a sequence number, then extensions would be lost.
295
- *
296
- * A special case are foreign keys, see extendForeignKeys().
297
- */
298
- function ensureArtifactNotProcessed( art ) {
299
- if (!model.options.testMode)
300
- return;
301
-
302
- if (art.kind !== 'key' && art.$effectiveSeqNo !== 0 && art.$effectiveSeqNo !== undefined) {
303
- // if the artifact already has a sequence number, then
304
- // extendArtifactAfter() was already called -> annotations would be lost.
305
- throw new CompilerAssertion('artifact already processed; extensions would be lost');
306
- }
307
- }
308
-
309
- /**
310
- * Create super annotate statements for remaining extensions
311
- */
312
- function createRemainingAnnotateStatements() {
313
- model.extensions = Object.values( model.$collectedExtensions );
314
- // TODO: testMode sort?
315
- model.extensions.forEach( createSuperAnnotate );
316
- // set _artifact links for “main extensions” late as it would disturb the
317
- // still existing old extend mechanism, see extendArtifactBefore(),
318
- // needed for LSP and friends:
319
- Object.values( model.sources ).forEach( setArtifactLinkForExtensions );
320
- Object.values( model.definitions ).forEach( setArtifactLinkForExtensions );
321
- }
322
-
323
- // TODO: delete again - if not, what about extensions in contexts/services?
324
- // Check test.lsp-api.js! Links in extensions are needed.
325
- function setArtifactLinkForExtensions( source ) {
326
- if (!source.extensions)
200
+ function moveDictExtensions( art, extensionsMap, artProp, extProp = artProp ) {
201
+ const extensions = extensionsMap[extProp || 'elements'];
202
+ if (!extensions)
327
203
  return;
328
- for (const ext of source.extensions) {
329
- if (!ext.name?.id)
330
- continue;
331
-
332
- const { name } = ext;
333
- const { path } = name;
334
- if (name._artifact === undefined) {
335
- resolvePath( name, ext.kind, ext ); // induce error & for LSP
336
- }
337
- else if (model.options.lspMode && path?.[0]._artifact === undefined) {
338
- // we don't use resolvePath(…,'extend'), as that would add a dependency
339
- resolveDefinitionName( ext );
340
- setArtifactLink( path[path.length - 1], name._artifact );
341
- }
342
- }
343
- }
344
-
345
- // For extendArtifactBefore(): ------------------------------------------------
346
-
347
- /**
348
- * Complain about invalid `extend service` and `extend context`.
349
- */
350
- function checkExtensionsKind( extensions, art ) {
351
204
  for (const ext of extensions) {
352
- const kind = ext.expectedKind?.val;
353
- if (kind && kind !== art.kind) {
354
- const loc = ext.expectedKind.location;
355
- if (kind === 'context' || kind === 'service') {
356
- // We have no real artifact during the construction of a super-annotate statement:
357
- const msgArgs = {
358
- '#': (art.kind === 'service' || art.kind === 'annotate') ? art.kind : 'std',
359
- art,
360
- kind,
361
- code: 'extend … with definitions',
362
- keyword: 'extend service',
363
- };
364
- // TODO v7: Discuss: make this an error?
365
- warning( 'ext-invalid-kind', [ loc, ext ], msgArgs, {
366
- std: 'Artifact $(ART) is not of kind $(KIND), use $(CODE) instead',
367
- annotate: 'There is no artifact $(ART), use $(CODE) instead',
368
- // do not mention 'extend context', that is not in CAPire
369
- service: 'Artifact $(ART) is not of kind $(KIND), use $(CODE) or $(KEYWORD) instead',
370
- } );
371
- }
372
- // TODO: Use similar checks for EXTEND ENTITY etc - 'ext-ignoring-kind'
373
- }
205
+ const members = art[artProp];
206
+ const realExtProp = extProp || (ext.enum ? 'enum' : 'elements');
207
+ if (!members && !checkExtensionDictionary( ext, art, artProp, realExtProp ))
208
+ continue;
209
+ forEachGeneric( ext, realExtProp, ( elemExt, name ) => {
210
+ if (elemExt.kind !== 'annotate' && elemExt.kind !== 'extend')
211
+ return; // definitions inside extend, already handled
212
+ // Remark: don't test elemExt.$duplicates, `annotate A (@Foo P, @Bar P)` should work
213
+ reportUnexpectedMemberExtensions( art, elemExt, artProp, name );
214
+ const elem = members?.[name] || annotateFor( art, extProp || 'elements', name );
215
+ setLink( elemExt.name, '_artifact', (elem.kind !== 'annotate' ? elem : null ) );
216
+ // null, because the element is not really there, just in a "super annotate"
217
+ if (elem.$duplicates !== true) // TODO: re-check, or just !elem.$duplicates
218
+ pushToDict( elem, '_extensions', elemExt );
219
+ });
374
220
  }
375
221
  }
376
222
 
@@ -379,8 +225,12 @@ function extend( model ) {
379
225
  * `{ prop: relevantExtensions, … }` where `relevantExtensions` are the extensions
380
226
  * which are relevant for the value of `art[prop]` after the application of extensions.
381
227
  *
382
- * Remark: it is not necessarily clear at this moment whether `art` has
383
- * `elements`, `enums`, `items`, etc.
228
+ * A special property is `$add`: it collects extensions for both `elements` (+
229
+ * `enum`) extensions and `includes` (also without elements, because the order
230
+ * of includes might influences which inludes wins for inherited annotations).
231
+ *
232
+ * Called in extendArtifactBefore(), where it is not necessarily clear whether
233
+ * `art` has `elements`, `enums`, `items`, etc.
384
234
  */
385
235
  function transformArtifactExtensions( art ) {
386
236
  // TODO: if extensions has more than one of returns,items,elements,enum, delete all those props
@@ -403,7 +253,7 @@ function extend( model ) {
403
253
  prop === 'groupBy' || prop === 'where' || prop === 'having' ||
404
254
  prop === 'orderBy' || prop === 'limit' || prop === 'length' ||
405
255
  prop === 'scale' || prop === 'precision' || prop === 'srid') {
406
- if (!isAutoItemsOrReturns)
256
+ if (!isAutoItemsOrReturns) // these props are ignored inside items/returns
407
257
  pushToDict( dict, prop, ext );
408
258
  }
409
259
  else if (prop === 'elements' || prop === 'enum') {
@@ -417,14 +267,19 @@ function extend( model ) {
417
267
  }
418
268
  else {
419
269
  pushToDict( dict, 'elements', ext ); // yes, enum → elements here
420
- if (ext.kind === 'extend' && !isAutoItemsOrReturns)
270
+ // if at least one elem/enum (TODO):
271
+ // && Object.keys( ext.elements ).some( elem => elem.kind !== 'extend' ))
272
+ // Add to $add if not already for includes:
273
+ if (ext.kind === 'extend' && !ext.includes)
421
274
  pushTo$add( dict, ext );
275
+ // TODO: issue error for ext on art having returns/items if ext has both
276
+ // include/actions/params and elements/enum (or handle that properly)
422
277
  }
423
278
  }
424
279
  else if (prop === 'returns') {
425
280
  pushToDict( dict, 'elements', ext );
426
281
  if (hasSecurityAnno( ext.returns ))
427
- checkReturnsExtension( ext, ext );
282
+ reportUnexpectedReturns( ext, ext );
428
283
  // create 'returns' for the super annotate, store in elements anyway
429
284
  if (!art.returns && art.kind === 'annotate')
430
285
  annotateCreate( art, '', art, 'returns' );
@@ -433,14 +288,14 @@ function extend( model ) {
433
288
  }
434
289
  else if (prop === 'actions' || prop === 'params') {
435
290
  pushToDict( dict, prop, ext );
436
- if (ext.kind === 'extend' && prop === 'actions' && !isAutoItemsOrReturns)
437
- pushTo$add( dict, ext );
438
291
  }
439
292
  }
440
293
  }
441
294
  art._extensions = dict;
442
295
  }
443
296
 
297
+ // Sort sources, select/sort extensions ---------------------------------------
298
+
444
299
  /**
445
300
  * Sort sources according to the reversed layered extension order without
446
301
  * reporting any messages.
@@ -467,12 +322,84 @@ function extend( model ) {
467
322
  setLink( model, '_sortedSources', scheduled );
468
323
  }
469
324
 
325
+ /**
326
+ * Traverses collected extensions for the given artifact, and for each property,
327
+ * select one (or sort them, e.g. for `includes`) if multiple extensions exist.
328
+ *
329
+ * Consider the module layer for the selection/sorting, and issue messages.
330
+ *
331
+ * Called at the beginning for each main artifact, and must not call
332
+ * resolvePath() then.
333
+ *
334
+ * @param {XSN.Artifact} art
335
+ */
336
+ function extendArtifactBefore( art ) {
337
+ // for main artifacts, move extensions from `$collectedExtensions` model dictionary:
338
+ if (!art._main && !art._outer && art._extensions === undefined &&
339
+ art.name && // TODO: probably just a workaround, check with TODO in getOriginRaw()
340
+ art.kind !== 'namespace') {
341
+ const { id } = art.name;
342
+ setLink( art, '_extensions', model.$collectedExtensions[id]?._extensions || null );
343
+ if (art._extensions && !art.builtin) { // keep extensions for builtin in $collectedExtensions
344
+ delete model.$collectedExtensions[id];
345
+ // TODO: if the extension mechanism has been completed, we could uncomment:
346
+ // art._extensions.forEach( ext => resolvePath( ext.name, ext.kind, ext )); // for LSP
347
+ // for now, we do that at the end of createRemainingAnnotateStatements()
348
+ }
349
+ }
350
+ if (art.kind === 'entity' && art.includes && !art._entityIncludes)
351
+ setEntityIncludes( art, art );
352
+
353
+ if (Array.isArray( art._extensions )) {
354
+ // TODO: the following function can now be simplified
355
+ // if (art.$inferred) console.log('CAI:', art.name, art.$inferred,art._extensions)
356
+ // With extensions, member appears in CSN, affects directly the rendering of
357
+ // elements etc. TODO: do that more specifically on the dicts (via symbol)
358
+ // Probably better: we could use the _extensions dict prop directly in to-csn
359
+ if (art.$inferred)
360
+ setExpandStatus( art, 'annotate' );
361
+ if (Array.isArray( art._extensions )) {
362
+ reportInvalidExtensionKind( art._extensions, art );
363
+ transformArtifactExtensions( art );
364
+ }
365
+ // console.log('EA:',require('../model/revealInternalProperties')
366
+ // .ref(art),Object.keys(art._extensions))
367
+ for (const prop in art._extensions) {
368
+ if (Object.hasOwn( art._extensions, prop ))
369
+ applyPropertyExtensions( art, prop );
370
+ }
371
+ }
372
+ }
373
+
374
+ /**
375
+ * Collect all includes which are entities in property `_entityIncludes`.
376
+ * This information is needed to kick-start the auto-redirection mechanism,
377
+ * i.e. must be called in extendArtifactBefore().
378
+ *
379
+ * A consequence is that a compiler-generated entity must never include an
380
+ * entity; the generated entity could be an auto-redirection target otherwise
381
+ * → an on-demand generated could change the auto-redirection behavior.
382
+ */
383
+ function setEntityIncludes( ext, art ) {
384
+ // TODO: better to call this once at the end of extendArtifactBefore()
385
+ setLink( art, '_entityIncludes', [] );
386
+ for (const ref of ext.includes) {
387
+ const name = resolveUncheckedPath( ref, 'include', ext );
388
+ const template = name && model.definitions[name];
389
+ if (template?.kind === 'entity')
390
+ art._entityIncludes.push( template );
391
+ }
392
+ }
393
+
470
394
  /**
471
395
  * For all `prop → extensions` in `art._extensions`, apply the extensions.
472
396
  * Currently only for annotations, the `doc` property, `columns` and type properties,
473
397
  * not for `elements` and other members.
474
398
  */
475
399
  function applyPropertyExtensions( art, prop ) {
400
+ if (prop === 'params' || prop === 'returns' || prop === 'elements')
401
+ return; // only for push-down
402
+
476
403
  const extensions = art._extensions;
477
404
  // annotations, `doc`, `includes`, `columns`, `length`, ...
478
405
  const scheduled = [];
@@ -498,20 +425,19 @@ function extend( model ) {
498
425
  }
499
426
  // Now apply the relevant extensions
500
427
  scheduled.reverse();
501
- art.$postponeInclude ??= 0; // add elems of includes before direct ones
502
428
  if (prop === 'includes' && !art.includes?.$original) {
503
429
  const $original = art.includes ?? [];
504
430
  art.includes = [ ...$original ];
505
431
  art.includes.$original = $original;
432
+ // extensions[prop] = scheduled;
506
433
  // console.log('APE:',art.name.id,art.includes.map( r => r._artifact?.name.id ))
507
434
  }
508
- if (prop === '$add') {
435
+ if (prop === '$add' || prop === 'actions') {
509
436
  extensions[prop] = scheduled;
510
- return; // the $add is applied in extendArtifactAdd()
437
+ return; // $add and actions are applied in extendArtifactAdd()
511
438
  }
512
439
  for (const ext of scheduled)
513
440
  applySingleExtension( art, ext, prop );
514
- delete extensions[prop];
515
441
  }
516
442
 
517
443
  function extensionOverwrites( ext, prop ) {
@@ -520,80 +446,20 @@ function extend( model ) {
520
446
  : !annotationHasEllipsis( ext[prop] );
521
447
  }
522
448
 
523
- // TODO: still a bit annotation assignment specific
524
- function reportDuplicateExtensions( extensions, prop, issue, index, art ) {
525
- // TODO: think about messages for these
526
- if (prop === 'elements' || prop === 'actions' || prop === 'columns' ||
527
- prop === 'params' || prop === '$add' )
528
- return; // extensions currently handled extra
529
- // TODO: columns?
530
- const isTypeParam = typeParameters.list.includes( prop );
531
- const isAnnoOrDoc = prop.charAt(0) === '@' || prop === 'doc';
532
- if (!isAnnoOrDoc && !isTypeParam && prop !== 'orderBy')
533
- return;
534
- if (issue) {
535
- if (prop === 'orderBy' && issue === 'unrelated') {
536
- for (const ext of extensions) {
537
- const clause = ext[prop];
538
- if (clause) {
539
- message( 'ext-unstable-order', [ clause[0]?.location || ext.location, ext ],
540
- { keyword: prop },
541
- // eslint-disable-next-line @stylistic/max-len
542
- 'Unstable order of entries in the $(KEYWORD) clause due to another extension in unrelated layer' );
543
- }
544
- }
545
- return;
546
- }
547
- // eslint-disable-next-line no-nested-ternary
548
- let msg = (index < 0)
549
- ? 'anno-unstable-array'
550
- : (issue === true)
551
- ? 'anno-duplicate'
552
- : 'anno-duplicate-unrelated-layer';
553
- if (!isAnnoOrDoc) {
554
- msg = (issue === true)
555
- ? 'ext-duplicate-extend-type'
556
- : 'ext-duplicate-extend-type-unrelated-layer';
557
- // not sure whether to repeat the extended artifact in the message (we
558
- // have the semantic location, after all)
559
- // extend-repeated-intralayer / extend-unrelated-layer
560
- }
561
- const variant = prop === 'doc' ? 'doc' : 'std';
562
- for (const ext of extensions) {
563
- const anno = ext[prop];
564
- if (anno && !anno.$errorReported) {
565
- message( msg, [ anno.name?.location || anno.location, ext ],
566
- { '#': variant, anno: prop, type: art } );
567
- }
568
- }
569
- }
570
- else if (index > 0) { // more than one set (not just ...)
571
- const variant = prop === 'doc' ? 'doc' : 'std';
572
- const msgid = (isAnnoOrDoc)
573
- ? 'anno-duplicate-same-file' // TODO: always ext-duplicate-…
574
- : 'ext-duplicate-same-file';
575
- while (index >= 0) { // do not report for trailing [...]
576
- const ext = extensions[index--];
577
- const anno = ext[prop];
578
- warning( msgid, [ anno.name?.location || anno.location, ext ],
579
- { '#': variant, prop, anno: prop } );
580
- }
581
- }
582
- }
583
-
584
- function applySingleExtension( art, ext, prop ) {
585
- if (prop === 'includes') {
586
- if (art.kind !== 'annotate' && !art._outer) { // TODO: why this check?
587
- // not with elem extension in targetAspect
588
- art.includes.push( ...ext.includes );
589
- // head of ref in in ext.includes must be set in _block of ext; for
590
- // remaining path items, effectiveType() has `art` as user
591
- // (alternatively, we could set some _user on `includes` items):
592
- for (const ref of ext.includes)
593
- resolveUncheckedPath( ref, 'include', ext );
594
- if (art.kind === 'entity')
595
- setEntityIncludes( ext, art );
596
- // console.log( 'ASI:',prop,art.name,ext,extensionsDict[id])
449
+ function applySingleExtension( art, ext, prop ) {
450
+ if (prop === 'includes') {
451
+ if (art.kind !== 'annotate' && !art._outer) { // TODO: why this check?
452
+ // not with elem extension in targetAspect
453
+ art.includes.push( ...ext.includes );
454
+ // head of ref in in ext.includes must be set in _block of ext; for
455
+ // remaining path items, effectiveType() has `art` as user
456
+ // (alternatively, we could set some _user on `includes` items):
457
+ for (const ref of ext.includes)
458
+ resolveUncheckedPath( ref, 'include', ext );
459
+ // TODO: some warning if duplicate ref
460
+ if (art.kind === 'entity')
461
+ setEntityIncludes( ext, art );
462
+ // console.log( 'ASI:',prop,art.name,ext,extensionsDict[id])
597
463
  }
598
464
  // art[prop] = (art[prop]) ? art[prop].concat( ext[prop] ) : ext[prop];
599
465
  }
@@ -610,10 +476,14 @@ function extend( model ) {
610
476
  error( 'extend-columns', [ ext.columns[$location], ext ], { '#': variant, art } );
611
477
  return;
612
478
  }
613
- if (!query.columns)
614
- query.columns = [ { location: query.from.location, val: '*' }, ...ext.columns ];
615
- else
479
+ if (!query.columns) {
480
+ query.columns = [ {
481
+ __proto__: XsnArtifact.prototype, location: query.from.location, val: '*',
482
+ }, ...ext.columns ];
483
+ }
484
+ else {
616
485
  query.columns.push( ...ext.columns );
486
+ }
617
487
  ext.columns.forEach( col => changeParentLinks( col, query ) );
618
488
  }
619
489
  else if (prop === 'groupBy' || prop === 'where' || prop === 'having' ||
@@ -626,76 +496,12 @@ function extend( model ) {
626
496
  }
627
497
  else {
628
498
  const result = applyAssignment( art[prop], ext[prop], ext, prop );
499
+ // Remark: result is ext[prop] if without [...]
629
500
  art[prop] = (result.name) ? result : Object.assign( {}, art[prop], result );
630
501
  }
631
502
  }
632
503
 
633
- function applyQueryClause( prop, ext, art ) {
634
- const { query } = art;
635
- const clause = ext[prop];
636
- const isArray = Array.isArray( clause );
637
-
638
- if (prop !== 'limit') {
639
- const items = isArray ? clause : [ clause ];
640
- for (const item of items) {
641
- item.$extended = prop;
642
- setLink( item, '_block', ext._block );
643
- setLink( item, '_outer', query );
644
- }
645
- }
646
- if (!query?.from?.path) {
647
- const variant = (query?.from || query)?.op?.val || 'std';
648
- const loc = isArray ? clause[$location] : clause.location;
649
- error( `extend-${ prop.toLowerCase() }`, [ loc, ext ], { '#': variant, art } );
650
- return;
651
- }
652
- if (isArray) {
653
- if (!query[prop])
654
- query[prop] = [];
655
- query[prop].push( ...clause );
656
- }
657
- else if (prop === 'where' || prop === 'having') {
658
- const existing = query[prop];
659
- if (!existing) {
660
- query[prop] = clause;
661
- }
662
- else if (existing.op?.val === 'and' &&
663
- existing.args.some( a => a.$extended === prop )) {
664
- existing.args.push( clause );
665
- }
666
- else {
667
- query[prop] = {
668
- op: { val: 'and', location: art.name.location },
669
- args: [ existing, clause ],
670
- location: clause.location,
671
- };
672
- }
673
- }
674
- else if (query[prop]) {
675
- error( 'ext-unexpected-sql-clause', [ clause.location, ext ], { art, keyword: prop } );
676
- }
677
- else {
678
- query[prop] = clause;
679
- }
680
- }
681
-
682
- function changeParentLinks( art, queryOrMain ) {
683
- // TODO: we might also change the implicit name (if name.id is a number,
684
- // adding the previous column lenght - 1) for better error messages
685
- const parent = art._parent;
686
- if (!art._parent)
687
- return;
688
- if (parent.kind === 'extend')
689
- art._parent = queryOrMain;
690
- if (art._main.kind === 'extend') // TODO: probably always
691
- art._main = queryOrMain._main;
692
- if (art._columnParent?.kind === 'extend')
693
- art._columnParent = queryOrMain;
694
- const subColumns = art.expand || art.inline;
695
- if (subColumns)
696
- subColumns.forEach( a => changeParentLinks( a, queryOrMain ) );
697
- forEachMember( art, a => changeParentLinks( a, queryOrMain ) );
698
- }
504
+ // Array annotations with `...`: ----------------------------------------------
699
505
 
700
506
  function applyAssignment( previousAnno, anno, art, annoName ) {
701
507
  const firstEllipsis = annotationHasEllipsis( anno );
@@ -738,6 +544,7 @@ function extend( model ) {
738
544
  }
739
545
  else {
740
546
  let upToSpec = !item.$errorReported && item.upTo;
547
+ // $errorReported: no anno-unexpected-upto-value with anno-invalid-upto-value
741
548
  while (prevPos < previousValue.length) {
742
549
  const prevItem = previousValue[prevPos++];
743
550
  result.push( prevItem );
@@ -748,7 +555,8 @@ function extend( model ) {
748
555
  }
749
556
  if (upToSpec && hasBase) {
750
557
  // non-matched UP TO; if there is no base to apply to, there is already an error.
751
- warning( null, [ item.upTo.location, art ], { anno: annoName, code: '... up to' },
558
+ warning( 'anno-unexpected-upto-value', [ item.upTo.location, art ],
559
+ { anno: annoName, code: '... up to' },
752
560
  'The $(CODE) value does not match any item in the base annotation $(ANNO)' );
753
561
  }
754
562
  }
@@ -764,7 +572,6 @@ function extend( model ) {
764
572
  }
765
573
 
766
574
  // For the `up to` specification, see ../../test3/Annotations/EllipsisUpTo/
767
-
768
575
  function equalUpTo( previousItem, upToSpec ) {
769
576
  if (!previousItem)
770
577
  return false;
@@ -816,11 +623,60 @@ function extend( model ) {
816
623
 
817
624
  function normalizeRef( node ) { // see to-csn.js
818
625
  const ref = pathName( node.path );
819
- // TODO XSN 7.1: get rid of name.variant (induces a wrong structure anyway)
626
+ // TODO XSN 7.2: get rid of name.variant (induces a wrong structure anyway)
820
627
  return node.variant ? `${ ref }#${ pathName( node.variant.path ) }` : ref;
821
628
  }
822
629
 
823
- // For extendArtifactAfter(): -------------------------------------------------
630
+ // Special properties: query clauses, type properties -------------------------
631
+
632
+ function applyQueryClause( prop, ext, art ) {
633
+ const { query } = art;
634
+ const clause = ext[prop];
635
+ const isArray = Array.isArray( clause );
636
+
637
+ if (prop !== 'limit') {
638
+ const items = isArray ? clause : [ clause ];
639
+ for (const item of items) {
640
+ item.$extended = prop;
641
+ setLink( item, '_block', ext._block );
642
+ setLink( item, '_outer', query );
643
+ }
644
+ }
645
+ if (!query?.from?.path) {
646
+ const variant = (query?.from || query)?.op?.val || 'std';
647
+ const loc = isArray ? clause[$location] : clause.location;
648
+ error( `extend-${ prop.toLowerCase() }`, [ loc, ext ], { '#': variant, art } );
649
+ return;
650
+ }
651
+ if (isArray) {
652
+ if (!query[prop])
653
+ query[prop] = [];
654
+ query[prop].push( ...clause );
655
+ }
656
+ else if (prop === 'where' || prop === 'having') {
657
+ const existing = query[prop];
658
+ if (!existing) {
659
+ query[prop] = clause;
660
+ }
661
+ else if (existing.op?.val === 'and' &&
662
+ existing.args.some( a => a.$extended === prop )) {
663
+ existing.args.push( clause );
664
+ }
665
+ else {
666
+ query[prop] = {
667
+ op: { val: 'and', location: art.name.location },
668
+ args: [ existing, clause ],
669
+ location: clause.location,
670
+ };
671
+ }
672
+ }
673
+ else if (query[prop]) {
674
+ error( 'ext-unexpected-sql-clause', [ clause.location, ext ], { art, keyword: prop } );
675
+ }
676
+ else {
677
+ query[prop] = clause;
678
+ }
679
+ }
824
680
 
825
681
  // Remarks on messages: we allow the type extensions only if the artifact
826
682
  // originally had that property → any check of the kind “type prop can only be
@@ -833,7 +689,7 @@ function extend( model ) {
833
689
  // - 'ext-unexpected-type-argument' (TODO) if the artifact does not have the prop
834
690
  // - 'ext-invalid-type-argument' if the value is wrong for extend (no overwrite)
835
691
  //
836
- // TODO v6: do not allow `extend … with (precision: …)` alone if original def also has `scale`
692
+ // TODO v8: do not allow `extend … with (precision: …)` alone if original def also has `scale`
837
693
  function applyTypeExtensions( art, ext, prop, scaleDiff ) {
838
694
  // console.log('ATE:',art?.[prop],ext?.[prop],scaleDiff)
839
695
  if (!ext?.[prop])
@@ -901,194 +757,332 @@ function extend( model ) {
901
757
  return parameters.includes( prop ) || parameters[0]?.name === prop;
902
758
  }
903
759
 
904
- function moveDictExtensions( art, extensionsMap, artProp, extProp = artProp ) {
905
- // TODO: setExpandStatus
906
- const extensions = extensionsMap[extProp || 'elements'];
907
- if (!extensions)
908
- return;
760
+ // Add new members ------------------------------------------------------------
909
761
 
910
- for (const ext of extensions) {
911
- forEachGeneric( ext, extProp || (ext.enum ? 'enum' : 'elements'), ( elemExt, name ) => {
912
- if (elemExt.kind !== 'annotate' && elemExt.kind !== 'extend') // TODO: specified elems
913
- return; // definitions inside extend, already handled
914
- checkRemainingMemberExtensions( art, elemExt, artProp, name );
915
- const elem = art[artProp]?.[name] || annotateFor( art, extProp || 'elements', name );
916
- setLink( elemExt.name, '_artifact', (elem.kind !== 'annotate' ? elem : null ) );
917
- // TODO: why null for annotate?
918
- ensureArtifactNotProcessed( elem );
919
- if (elem.$duplicates !== true) // TODO: re-check
920
- pushToDict( elem, '_extensions', elemExt );
921
- });
762
+ /**
763
+ * Extend artifact with additional elements and actions: via includes and/or
764
+ * extensions. This happens _after_ `populateArtifact`, i.e. after eventually
765
+ * having inferred the elements/... from an "origin".
766
+ *
767
+ * `art` can also be a pseudo artifact in `items`.
768
+ */
769
+ function extendArtifactAdd( art ) {
770
+ const { includes, _extensions: extensions } = art;
771
+ if (includes) {
772
+ // propagation of core-compiler relevant annotation assignments:
773
+ propagateEarly( art, '@cds.autoexpose' );
774
+ propagateEarly( art, '@fiori.draft.enabled' );
775
+ reportInvalidIncludes( art );
922
776
  }
923
- }
777
+ else if (!extensions) { // semantically unnecessary, just for speed-up
778
+ return;
779
+ }
780
+ if (art.items || art.targetAspect || art.returns)
781
+ return; // adding enums/elements is pushed down
924
782
 
925
- function annotateFor( art, prop, name ) {
926
- const base = annotateBase( art );
927
- if (name === '' && prop === 'params')
928
- return base.returns || annotateCreate( base, name, base, 'returns' );
929
- const dict = base[prop] || (base[prop] = Object.create( null ));
930
- if (name == null)
931
- return dict;
932
- return dict[name] || annotateCreate( dict, name, base );
933
- }
783
+ const realArt = outerArtifact( art ); // e.g. if `art = realArt.items`
934
784
 
935
- function annotateBase( art ) {
936
- while (art._outer) // TODO: think about anonymous target aspect
937
- art = art._outer;
938
- if (art.kind === 'annotate')
939
- return art;
785
+ // params: no new params can be added via extend yet (annotation is ok)
786
+ if (!art.params && extensions?.params &&
787
+ (art.kind === 'action' || art.kind === 'function' ||
788
+ art.kind === 'entity' && art.query))
789
+ art.params = Object.create(null); // for moveDictExtensions()
940
790
 
941
- // TODO: more to do if annotate can have `returns` property
942
- if (art.kind === 'select')
943
- art = art._parent;
944
- if (art._main)
945
- return annotateFor( art._parent, kindProperties[art.kind].dict, art.name.id );
791
+ // foreign keys: TODO - do something here?
946
792
 
947
- const { id } = art.name;
948
- return model.$collectedExtensions[id] ||
949
- annotateCreate( model.$collectedExtensions, id );
950
- }
793
+ const { elements } = art;
794
+ if (extensions?.$add) {
795
+ for (const ext of extensions.$add)
796
+ addExtensionEnum( ext, realArt, art );
797
+ }
951
798
 
952
- function annotateCreate( dict, id, parent, prop ) {
953
- const annotate = {
954
- kind: 'annotate',
955
- name: { id, location: genLocation },
956
- $inferred: '',
957
- location: genLocation,
958
- };
959
- if (parent) {
960
- setLink( annotate, '_parent', parent );
961
- setLink( annotate, '_main', parent._main || parent );
799
+ if (!elements) // elements and actions can only added to defs with elements
800
+ return;
801
+ // elements: direct includes + elements → extended includes + elements
802
+ if (includes?.some( i => i._artifact?.elements ) ||
803
+ extensions?.$add?.some( e => e.elements || e.enum )) {
804
+ // TODO: calculate $add here, not in extendArtifactBefore(), consider
805
+ // unreleated layer messages (elements + includes with elements)
806
+ art.elements = Object.create( null );
807
+ art.elements[$location] = elements[$location];
808
+ if (elements[$inferred])
809
+ art.elements[$inferred] = elements[$inferred];
810
+ const def = { elements, includes: includes?.$original || includes };
811
+ const postponeFirst = postponeFirstInclude( def.includes, elements );
812
+ let addedLast = addExtensionMembers( def, realArt, art, 'elements', postponeFirst );
813
+ for (const ext of extensions?.$add || []) {
814
+ const extInclude = ext.includes?.[0];
815
+ if (extInclude) {
816
+ const postpone = extInclude.$postponeInclude ?? 0;
817
+ extInclude.$postponeInclude = postpone + addedLast;
818
+ addedLast = addExtensionMembers( ext, realArt, art, 'elements', postpone );
819
+ }
820
+ else {
821
+ addedLast += addExtensionMembers( ext, realArt, art, 'elements', -1 );
822
+ }
823
+ }
824
+ if (includes)
825
+ reportRedefinitionThroughIncludes( art, 'elements' );
826
+ }
827
+
828
+ // actions: via includes (also extended ones) → direct actions → extended actions
829
+ if (art.kind === 'type') { // TODO: what about event ?
830
+ if (includes)
831
+ reportTypeIncludesWithActions( art );
832
+ }
833
+ else if ((art.kind === 'entity' || art.kind === 'aspect') &&
834
+ (extensions?.actions || includes?.some( ref => ref._artifact?.actions ))) {
835
+ const { actions } = art;
836
+ art.actions = Object.create( null );
837
+ if (actions)
838
+ art.actions[$location] = actions[$location];
839
+ for (const ref of includes || [])
840
+ applyInclude( ref, null, art, 'actions' );
841
+ if (actions)
842
+ addExtensionMembers( { actions }, art, art, 'actions' );
843
+ for (const ext of extensions?.actions || [])
844
+ addExtensionMembers( ext, art, art, 'actions' );
845
+ if (includes)
846
+ reportRedefinitionThroughIncludes( art, 'actions' );
962
847
  }
963
- dict[prop || id] = annotate;
964
- return annotate;
965
848
  }
966
849
 
967
- function checkReturnsExtension( ext, art ) {
968
- const msgId = hasSecurityAnno( ext.returns )
969
- ? 'ext-unexpected-returns-sec'
970
- : 'ext-unexpected-returns';
971
- message( msgId, [ ext.returns.location, ext ],
972
- { '#': art.kind, keyword: 'returns' } );
973
- // Do not put completely wrong returns into a “super annotate” statement;
974
- // this could induce consequential errors with [..., …]:
975
- return art.kind === 'action' || art.kind === 'function';
976
- }
850
+ function addExtensionMembers( ext, art, obj, prop, postpone = -1 ) {
851
+ if (ext.kind)
852
+ dependsOnSilent( art, ext ); // TODO: really do that here?
853
+ if (ext.kind === 'annotate') // is also used for extensions.actions
854
+ return 0;
855
+ // art depends silently on ext (inverse to normal dep!), still necessary?
856
+ const { includes } = ext;
857
+ const extDict = ext[prop];
858
+ if (!extDict && !includes?.some( i => i._artifact?.[prop] ))
859
+ return 0;
977
860
 
978
- function extendHandleReturns( ext, art ) {
979
- warning( 'ext-expecting-returns', [ ext.name.location, ext ], {
980
- '#': art.kind, keyword: 'returns', code: 'annotate ‹name› with returns { … }',
981
- }, {
982
- std: 'Expected $(CODE)', // unused variant
983
- action: 'Expected $(KEYWORD) when annotating action return structure, i.e. $(CODE)',
984
- function: 'Expected $(KEYWORD) when annotating function return structure, i.e. $(CODE)',
985
- // eslint-disable-next-line @stylistic/max-len
986
- annotate: 'Expected $(KEYWORD) when annotating a return structure of an unknown action or function, i.e. $(CODE)',
987
- } );
861
+ const artDict = obj[prop];
862
+ if (ext.kind &&
863
+ (obj.$inferred || artDict?.[$inferred] || art.query && prop === 'elements') &&
864
+ (extDict || ext.includes))
865
+ reportExtensionOnGenerated( ext, art, prop, extDict );
866
+ let index = 0;
867
+ for (const name in extDict || {}) { // remark: `|| {}` not really necessary
868
+ const adding = extDict[name];
869
+ if (adding.kind === 'annotate' || adding.kind === 'extend')
870
+ continue;
871
+ while (postpone === 0)
872
+ postpone = applyInclude( includes[index++], includes[index], art, prop );
873
+ const existing = artDict[name];
874
+ if (!existing || existing.$inferred === 'include')
875
+ artDict[name] = adding;
876
+ else
877
+ dictAdd( artDict, name, adding, reportDuplicate );
878
+ initMember( adding, art, prop );
879
+ if (!adding.$inferred) // not for derived members (with aspect include)
880
+ --postpone; // also when members shadows included one
881
+ }
882
+ if (prop !== 'elements' || !includes?.[index])
883
+ return -1 - postpone; // number of elements added last (after includes)
884
+ while (index < includes.length)
885
+ applyInclude( includes[index++], null, art, prop );
886
+ return 0;
988
887
  }
989
888
 
990
- function checkRemainingMemberExtensions( parent, ext, prop, name ) {
991
- // console.log('CRME:',prop,name,parent,ext)
992
-
993
- // TODO: just use `ext-undefined-element` etc also when no elements are there
994
- // at all (but use an extra text variant and the `{…}` location). Reason: we
995
- // might allow to add new actions, and an `annotate` on an undefined action
996
- // should not lead to another message id. We would use and extra message id
997
- // if we consider this an error or such sub annotates are then ignored
998
- // (i.e. not put into the "super annotate").
999
- const dict = parent[prop];
1000
- const securityRelevant = hasSecurityAnno( ext ) ? '-sec' : '';
1001
- const inSuperAnnotate = (parent.kind === 'annotate');
1002
- if (!dict && !securityRelevant) {
1003
- if (inSuperAnnotate) // no check in super annotate statement
1004
- return;
1005
- // TODO: check - for each name? - better locations
1006
- const location = ext._parent?.[prop]?.[$location] || ext.name.location;
1007
- // Remark: no `elements` dict location with `annotate Main:elem`
1008
- switch (prop) {
1009
- // TODO: change texts, somehow similar to checkDefinitions() ?
1010
- case 'foreignKeys':
1011
- case 'elements':
1012
- case 'enum': // TODO: extra?
1013
- warning( 'anno-unexpected-elements', [ location, ext._parent ],
1014
- { '#': (parent._effectiveType?.kind === 'entity') ? 'entity' : 'std' }, {
1015
- std: 'Elements only exist in entities, types or typed constructs',
1016
- entity: 'Elements of entity types can\'t be annotated',
1017
- // TODO: extra msg for 'entity'? → this is some other
1018
- // situation, somehow similar when trying to annotate elements
1019
- // of target entity
1020
- } );
1021
- break;
1022
- case 'params':
1023
- warning( 'anno-unexpected-params', [ location, ext._parent ], {},
1024
- 'Parameters only exist for actions or functions' );
1025
- break;
1026
- case 'actions':
1027
- if (canBeDraftMember( name, parent, draftBoundActions ))
1028
- return;
1029
- // TODO: use extra text variant and location of dictionary - no
1030
- notFound( 'ext-undefined-action', ext.name.location, ext,
1031
- { '#': 'action', art: parent, name } );
1032
- break;
1033
- default:
1034
- if (model.options.testMode)
1035
- throw new CompilerAssertion(`Missing case for prop: ${ prop }`);
1036
- }
889
+ function addExtensionEnum( ext, art, obj ) {
890
+ // TODO: test `extend Enum with Include;
891
+ const artDict = obj.enum;
892
+ if (!artDict) {
893
+ if (ext.enum)
894
+ error( 'def-unexpected-enum', [ ext.enum[$location] || ext.name.location, ext ], {} );
895
+ return;
1037
896
  }
1038
- else if (!dict?.[name]) {
1039
- if (inSuperAnnotate && !securityRelevant)
1040
- return; // there was already a warning for the parent
1041
- // TODO: make variant `returns` an auto-variant for ($ART) ?
1042
- const inReturns = parent._parent?.returns;
1043
- switch (prop) {
1044
- case 'elements':
1045
- if (canBeDraftMember( name, parent, draftElements ))
1046
- break;
1047
- notFound( `ext-undefined-element${ securityRelevant }`, ext.name.location, ext,
1048
- { '#': (inReturns ? 'returns' : 'element'), name },
1049
- parent.elements );
1050
- break;
1051
- case 'enum': // TODO: extra msg id?
1052
- notFound( `ext-undefined-element${ securityRelevant }`, ext.name.location, ext,
1053
- { '#': (inReturns ? 'enum-returns' : 'enum'), name },
1054
- parent.enum );
1055
- break;
1056
- case 'foreignKeys':
1057
- notFound( `ext-undefined-key${ securityRelevant }`, ext.name.location, ext,
1058
- { name }, parent.foreignKeys );
1059
- break;
1060
- case 'params':
1061
- notFound( `ext-undefined-param${ securityRelevant }`, ext.name.location, ext,
1062
- { '#': 'param', name },
1063
- parent.params );
1064
- break;
1065
- case 'actions':
1066
- if (canBeDraftMember( name, parent, draftBoundActions ))
1067
- break;
1068
- notFound( `ext-undefined-action${ securityRelevant }`, ext.name.location, ext,
1069
- { '#': 'action', name },
1070
- parent.actions );
1071
- break;
1072
- default:
1073
- if (model.options.testMode)
1074
- throw new CompilerAssertion(`Missing case for prop: ${ prop }`);
897
+ if (ext.kind)
898
+ dependsOnSilent( art, ext ); // TODO: really do that here?
899
+ // art depends silently on ext (inverse to normal dep!), still necessary?
900
+ const extDict = ext.enum || ext.elements;
901
+ if (!extDict) // i.e. includes-only extension
902
+ return;
903
+ const notEnum = [];
904
+ if (ext.kind && (art.$inferred || art.query))
905
+ reportExtensionOnGenerated( ext, art, 'enum', extDict );
906
+ for (const name in extDict) {
907
+ const adding = extDict[name];
908
+ if (adding.kind === 'annotate' || adding.kind === 'extend')
909
+ continue;
910
+ if (adding.kind === 'enum' || adding.$syntax === 'or-enum') {
911
+ notEnum.addedAnyway = true;
912
+ adding.kind = 'enum';
913
+ initMember( adding, art, 'enum' );
914
+ dictAdd( artDict, name, adding, reportDuplicate );
915
+ }
916
+ else {
917
+ notEnum.push( name ); // not added to enum dict!
1075
918
  }
1076
919
  }
920
+ if (notEnum.length) {
921
+ error( 'ext-unexpected-element', [ extDict[$location], ext ],
922
+ { code: 'extend … with enum', names: notEnum } );
923
+ }
924
+ else if (notEnum.addedAnyway &&
925
+ (!obj.type || obj.type.$inferred || (art._main || art).query)) {
926
+ // TODO: really improve msg id and text
927
+ error( 'extend-type', [ extDict[$location], ext ], {},
928
+ 'Only structures or enum types can be extended with elements/enums' );
929
+ }
930
+ else if (!ext.enum) {
931
+ warning( 'ext-expecting-enum', [ extDict[$location], ext ],
932
+ { code: 'extend … with enum' }, 'Use $(CODE) when extending enums' );
933
+ }
1077
934
  }
1078
935
 
1079
- function notFound( msgId, location, address, args, validDict ) {
1080
- const msg = message( msgId, [ location, address ], args );
1081
- attachAndEmitValidNames( msg, validDict );
936
+ function postponeFirstInclude( includes, members ) {
937
+ if (!includes?.length)
938
+ return -1;
939
+ const postpone = includes[0].$postponeInclude;
940
+ if (postpone != null || !members) // TODO v8: `(postpone !== -1)`
941
+ return postpone ?? 0;
942
+ // compatibility: includes in definition - if elements cover all elements from
943
+ // includes, use provided order - TODO v8: only for CSN input
944
+ for (const ref of includes) {
945
+ const elements = ref._artifact?.elements;
946
+ if (elements && Object.keys( elements ).some( name => !members[name] ))
947
+ return 0; // some element in some include not covered → normal order
948
+ }
949
+ return -1; // includes last = use provided element order
1082
950
  }
1083
951
 
1084
- // For createRemainingAnnotateStatements(): -----------------------------------
952
+ function applyInclude( ref, nextRef, art, prop ) {
953
+ const include = ref._artifact; // already resolved
954
+ const members = include?.[prop];
955
+ if (!members)
956
+ return nextRef ? nextRef.$postponeInclude ?? 0 : -1;
1085
957
 
1086
- function createSuperAnnotate( annotate ) {
1087
- const extensions = annotate._extensions;
1088
- if (extensions && !annotate._main) {
958
+ // If elements `texts` and `localized` from an included entity are (likely)
959
+ // compiler-generated, users won't expect them to be included:
960
+ const checkForLocalized = prop === 'elements' && include.kind === 'entity' &&
961
+ !include.query && withLocalizedData( include );
962
+ const propagateKeys = art.kind !== 'type' || model.options.v6KeyPropagation;
963
+
964
+ for (const name in members) {
965
+ const existing = art[prop][name];
966
+ if (existing && existing.$inferred !== 'include' ||
967
+ checkForLocalized && (name === 'texts' || name === 'localized'))
968
+ continue; // shadowed by directly defined/extended element, or localized
969
+ const origin = members[name];
970
+ if (origin.$duplicates) // duplicates are not included
971
+ continue;
972
+ const location = weakRefLocation( ref );
973
+ const proxy = linkToOrigin( origin, name, null, null, location );
974
+ setLink( proxy, '_block', origin._block ); // TODO: why is this necessary?
975
+ proxy.$inferred = 'include';
976
+ if (origin.key && propagateKeys)
977
+ proxy.key = Object.assign( { $inferred: 'include' }, origin.key );
978
+ // TODO: origin.$syntax === 'calc' test?
979
+ if (origin.value && origin.$syntax === 'calc') {
980
+ // TODO: If paths become invalid in the new artifact, should we mark
981
+ // all usages in the expressions? Possibly just the first one?
982
+ proxy.value = { $inferred: 'include', ...copyExpr( origin.value, location, true ) };
983
+ proxy.$syntax = 'calc';
984
+ createAndLinkCalcDepElement( proxy );
985
+ setLink( proxy, '_calcOrigin', origin._calcOrigin || origin );
986
+ }
987
+
988
+ setLink( proxy, '_parent', art );
989
+ setLink( proxy, '_main', art );
990
+ initMember( proxy, art );
991
+ dictAdd( art[prop], name, proxy );
992
+ // delayed reporting of duplicates via reportRedefinitionThroughIncludes()
993
+ }
994
+ return nextRef ? nextRef.$postponeInclude ?? 0 : -1;
995
+ }
996
+
997
+ /**
998
+ * Return true if include (with `name` and `elements`) in `ext` highly likely
999
+ * contain elements `texts` and `localized` which are compiler-generated for
1000
+ * localized data. Due to recompilation, we cannot just check the `$inferred`
1001
+ * property in the XSN, but need to apply an heuristics.
1002
+ * (We could still use $inferred as speed-up if run without `testMode`.)
1003
+ *
1004
+ * It is as follows: the elements `texts` and `localized` in entity `‹E›` and
1005
+ * the entity `‹E›.texts` are considered compiler-generated for Localized Data if
1006
+ *
1007
+ * - `‹E›.texts` has a key element `locale`
1008
+ * (TODO: currently weakend to “entity exists”)
1009
+ * - `texts` of `‹E›` is an unmanaged composition to `‹E›.texts`
1010
+ * - `localized` of `‹E›` is an unmanaged association to `‹E›.texts`
1011
+ */
1012
+ function withLocalizedData( { name, elements } ) { // TODO: use it again
1013
+ const textsEntityName = `${ name.id }.texts`;
1014
+ // if we test (again) for element `locale` - it might come from an extend or
1015
+ // TextsAspect include, which might not have yet applied
1016
+ if (!model.definitions[textsEntityName])
1017
+ return false;
1018
+ const { texts, localized } = elements ?? {};
1019
+ return texts?.target && localized?.target && texts.on && localized.on &&
1020
+ resolveUncheckedPath( texts.target, 'target', texts ) === textsEntityName &&
1021
+ resolveUncheckedPath( localized.target, 'target', localized ) === textsEntityName &&
1022
+ resolveUncheckedPath( texts.type, 'type', texts ) === 'cds.Composition' &&
1023
+ resolveUncheckedPath( localized.type, 'type', localized ) === 'cds.Association';
1024
+ }
1025
+
1026
+ function initMember( member, parent, prop = 'elements' ) {
1027
+ if (member._parent === parent) // origin element → nothing to do
1028
+ return;
1029
+ changeParentLinks( member, parent );
1030
+ if (member.targetAspect?.elements)
1031
+ setLink( member.targetAspect, '_parent', member._parent );
1032
+
1033
+ if (member.kind === 'action' || member.kind === 'function')
1034
+ initBoundSelfParam( member.params, member._main );
1035
+
1036
+ if (parent[prop]?.[$inferred])
1037
+ setExpandStatus( parent, 'extend' );
1038
+
1039
+ if (member.$syntax === 'or-enum' && member.value && member.kind === 'element') {
1040
+ member.$syntax = 'calc';
1041
+ createAndLinkCalcDepElement( member );
1042
+ }
1043
+ }
1044
+
1045
+ function changeParentLinks( art, parentOrMain ) { // or just `parentOrMain`?
1046
+ // TODO: we might also change the implicit name (if name.id is a number,
1047
+ // adding the previous column lenght - 1) for better error messages
1048
+ if (art._parent?.kind === 'extend')
1049
+ setLink( art, '_parent', parentOrMain );
1050
+ if (art._outer?.kind === 'extend')
1051
+ setLink( art, '_outer', parentOrMain );
1052
+ if (art._main?.kind === 'extend')
1053
+ setLink( art, '_main', parentOrMain._main || parentOrMain );
1054
+ if (art._columnParent?.kind === 'extend')
1055
+ art._columnParent = parentOrMain;
1056
+ const subColumns = art.expand || art.inline;
1057
+ if (subColumns)
1058
+ subColumns.forEach( a => changeParentLinks( a, parentOrMain ) );
1059
+ forEachMember( initItemsLinks( art, art._block ),
1060
+ a => changeParentLinks( a, parentOrMain ) );
1061
+ }
1062
+
1063
+ // Create “super” ANNOTATE statements -----------------------------------------
1064
+
1065
+ /**
1066
+ * Create super annotate statements for remaining extensions.
1067
+ * Called near the end of the compilation.
1068
+ */
1069
+ function createRemainingAnnotateStatements() {
1070
+ model.extensions = Object.values( model.$collectedExtensions );
1071
+ // TODO: testMode sort?
1072
+ model.extensions.forEach( createSuperAnnotate );
1073
+ // set _artifact links for “main extensions” late as it would disturb the
1074
+ // still existing old extend mechanism, see extendArtifactBefore(),
1075
+ // needed for LSP and friends:
1076
+ Object.values( model.sources ).forEach( setArtifactLinkForExtensions );
1077
+ Object.values( model.definitions ).forEach( setArtifactLinkForExtensions );
1078
+ }
1079
+
1080
+ function createSuperAnnotate( annotate ) {
1081
+ const extensions = annotate._extensions;
1082
+ if (extensions && !annotate._main) {
1089
1083
  const art = model.definitions[annotate.name.id];
1090
1084
  for (const ext of extensions)
1091
- checkRemainingMainExtensions( art, ext ); // induce messages for extension path
1085
+ reportExtensionOnBuiltin( art, ext ); // induce messages for extension path
1092
1086
  if (art?.builtin && art.kind !== 'namespace') { // TODO: do not set `builtin` on cds, cds.hana
1093
1087
  setLink( annotate, '_extensions', art._extensions ); // for messages and member extensions
1094
1088
  // direct annotations on builtins or on the builtins for propagation, and
@@ -1108,716 +1102,559 @@ function extend( model ) {
1108
1102
  forEachMember( annotate, createSuperAnnotate );
1109
1103
  }
1110
1104
 
1111
- function checkRemainingMainExtensions( art, ext ) {
1112
- const refCtx = extensionRefContext( ext );
1113
- if (resolvePath( ext.name, refCtx, ext ) && art?.builtin) {
1114
- if (ext.kind === 'extend') {
1115
- // extending built-ins with elements/enums already gives an error
1116
- warning( 'ext-unexpected-builtin', [ ext.name.location, ext ], {}, // error v8?
1117
- 'Built-in types should not be extended' ); // keep the text general
1118
- const typeProp = typeParameters.list.find( p => ext[p] );
1119
- if (typeProp) {
1120
- const location = ext.$typeArgs?.[$location] || ext[typeProp].location;
1121
- message( 'ext-unexpected-type-property', [ location, ext ], {}, // error v7
1122
- 'Built-in types can\'t be extended with type properties' );
1123
- // see also 'ext-invalid-type-property'
1124
- }
1125
- }
1126
- else {
1127
- info( 'anno-builtin', [ ext.name.location, ext ], {} ); // TODO: better location?
1128
- }
1129
- // TODO: remove built-ins as CC candidates via accept property of ./shared.js
1130
- }
1131
- }
1132
-
1133
- // Issue messages for annotations on namespaces and builtins
1134
- // (TODO: really here?, probably split main artifacts vs returns)
1135
- // see also createRemainingAnnotateStatements() where similar messages are reported
1136
- function checkAnnotate( construct, art ) {
1137
- // TODO: Handle extend statements properly: Different message for empty extend?
1105
+ // TODO: delete again - if not, what about extensions in contexts/services?
1106
+ // Check test.lsp-api.js! Links in extensions are needed.
1107
+ function setArtifactLinkForExtensions( source ) {
1108
+ if (!source.extensions)
1109
+ return;
1110
+ for (const ext of source.extensions) {
1111
+ if (!ext.name?.id)
1112
+ continue;
1138
1113
 
1139
- // --> without art._block, art not found
1140
- if (construct.kind === 'annotate' && art._block?.$frontend === 'cdl') {
1141
- if (construct.returns && art.kind !== 'action' && art.kind !== 'function' ) {
1142
- // See moveReturnsExtensions()
1114
+ const { name } = ext;
1115
+ const { path } = name;
1116
+ if (name._artifact === undefined) {
1117
+ resolvePath( name, ext.kind, ext ); // induce error & for LSP
1143
1118
  }
1144
- else if (!construct.returns &&
1145
- (art.kind === 'action' || art.kind === 'function') && construct.elements) {
1146
- warning( 'ext-expecting-returns', [ construct.name.location, construct ], {
1147
- '#': art.kind, keyword: 'returns', code: 'annotate ‹name› with returns { … }',
1148
- }, {
1149
- std: 'Expected $(CODE)', // unused variant
1150
- action: 'Expected $(KEYWORD) when annotating action return structure, i.e. $(CODE)',
1151
- function: 'Expected $(KEYWORD) when annotating function return structure, i.e. $(CODE)',
1152
- } );
1119
+ else if (model.options.lspMode && path?.[0]._artifact === undefined) {
1120
+ // we don't use resolvePath(…,'extend'), as that would add a dependency
1121
+ resolveDefinitionName( ext );
1122
+ setArtifactLink( path[path.length - 1], name._artifact );
1153
1123
  }
1154
1124
  }
1155
1125
  }
1156
1126
 
1157
- // extend, mainly old-style ---------------------------------------------------
1158
-
1159
- function addedElements( art ) {
1160
- return Object.values( art.elements )
1161
- .reduce( ( acc, elem ) => (elem.kind === 'extend' ? acc : acc + 1), 0 );
1127
+ function annotateFor( art, prop, name ) {
1128
+ const base = annotateBase( art );
1129
+ if (name === '' && prop === 'params')
1130
+ return base.returns || annotateCreate( base, name, base, 'returns' );
1131
+ const dict = base[prop] || (base[prop] = Object.create( null ));
1132
+ if (name == null)
1133
+ return dict;
1134
+ return dict[name] || annotateCreate( dict, name, base );
1162
1135
  }
1163
1136
 
1164
- /**
1165
- * Extend artifact with additional elements and actions: via includes and/or
1166
- * extensions. This happens _after_ `populateArtifact`, i.e. after eventually
1167
- * having inferred the elements/... from an "origin".
1168
- */
1169
- function extendArtifactAdd( art ) {
1170
- const { includes } = art;
1171
- if (includes) {
1172
- if (includes.$original) // if extensions with includes:
1173
- art.includes = includes.$original; // original includes have been stored
1174
- if (art.includes?.length)
1175
- applyIncludes( art, art ); // apply includes provided with definition
1176
- else if (art.elements) // next include only after elements so far
1177
- art.$postponeInclude += addedElements( art );
1178
-
1179
- art.includes = includes;
1180
- // early propagation of specific annotation assignments
1181
- // TODO: propagate in effectiveType() ?
1182
- propagateEarly( art, '@cds.autoexpose' );
1183
- propagateEarly( art, '@fiori.draft.enabled' );
1184
- }
1185
- if (art._extensions?.$add)
1186
- extendArtifact( art._extensions.$add, art ); // apply extensions
1187
- checkRedefinitionThroughIncludes( art, 'elements' );
1188
- checkRedefinitionThroughIncludes( art, 'actions' );
1189
- }
1137
+ function annotateBase( art ) {
1138
+ while (art._outer) // TODO: think about anonymous target aspect
1139
+ art = art._outer;
1140
+ if (art.kind === 'annotate')
1141
+ return art;
1190
1142
 
1191
- /**
1192
- * Extend artifact `art` by `extensions`. `cyclicIncludeNames` can have values:
1193
- * - falsy: try to apply include, then perform extend and annotate
1194
- * - an array of include names with cyclic dependencies: includes are not applied,
1195
- * extend and annotate is performed
1196
- * remark: we could have applied includes without cycle
1197
- *
1198
- * Returns true if extend and annotate are performed.
1199
- *
1200
- * @param {XSN.Extension[]} extensions
1201
- * @param {XSN.Definition} art
1202
- * @param {String[]|false} [cyclicIncludeNames=false]
1203
- */
1204
- function extendArtifact( extensions, art ) {
1205
- if (!art.query && !art._main && !art._outer) { // TODO: remove _entities
1206
- model._entities.push( art ); // add structure with includes in dep order
1207
- }
1208
- // TODO: complain if $inferred
1209
- // checkExtensionsKind( extensions, art );
1210
- extendMembers( extensions, art );
1211
- reportIncludeCollisions( art );
1212
- // TODO: complain about element extensions inside projection
1213
- return true;
1143
+ // TODO: more to do if annotate can have `returns` property
1144
+ if (art.kind === 'select')
1145
+ art = art._parent;
1146
+ if (art._main)
1147
+ return annotateFor( art._parent, kindProperties[art.kind].dict, art.name.id );
1148
+
1149
+ const { id } = art.name;
1150
+ return model.$collectedExtensions[id] ||
1151
+ annotateCreate( model.$collectedExtensions, id );
1214
1152
  }
1215
1153
 
1216
- function reportIncludeCollisions( art ) {
1217
- const grouped = Object.create( null );
1218
- for (const {
1219
- prop, name, existing, elem,
1220
- } of includeCollisions) {
1221
- const key = `${ prop }:${ name }`;
1222
- if (!grouped[key])
1223
- grouped[key] = { prop, name, collisions: new Set( [ existing ] ) };
1224
- grouped[key].collisions.add( elem );
1225
- }
1226
- for (const key in grouped) {
1227
- const { prop, name, collisions } = grouped[key];
1228
- const member = art[prop]?.[name];
1229
- if (member?.$inferred === 'include') {
1230
- const arts = [ ...collisions ].map( m => m._origin._main );
1231
- message( 'ext-duplicate-include', [ art.name.location, member ],
1232
- { '#': prop, name, sorted_arts: arts } );
1233
- }
1154
+ function annotateCreate( dict, id, parent, prop ) {
1155
+ const annotate = {
1156
+ __proto__: XsnArtifact.prototype,
1157
+ kind: 'annotate',
1158
+ name: { __proto__: XsnName.prototype, id, location: genLocation },
1159
+ $inferred: '',
1160
+ location: genLocation,
1161
+ };
1162
+ if (parent) {
1163
+ setLink( annotate, '_parent', parent );
1164
+ setLink( annotate, '_main', parent._main || parent );
1234
1165
  }
1235
- includeCollisions.length = 0;
1166
+ dict[prop || id] = annotate;
1167
+ return annotate;
1236
1168
  }
1237
1169
 
1238
- function extendMembers( extensions, art ) {
1239
- // only called in extendArtifact()
1240
- // TODO: do the whole extension stuff lazily if the elements are requested
1241
- const elemExtensions = [];
1242
- // if (art._main) // extensions already sorted for main artifacts
1243
- // extensions.sort( layers.compareLayer );
1244
- // TODO: use same sequence as in chooseAssignment() - better: use common code with that fn
1245
- // console.log('EM:',art.name,extensions,art._extensions)
1246
- for (const ext of extensions) { // those in extMap.includes
1247
- if (art.$inferred === 'include') {
1248
- error( 'ref-expected-direct-structure', [ ext.name.location, ext ],
1249
- { '#': 'elements', art } );
1250
- }
1251
- else if (art.$inferred) {
1252
- error( 'extend-for-generated', [ ext.name.location, ext ], { art, keyword: 'extend' },
1253
- 'You can\'t use $(KEYWORD) on the generated $(ART)' ); // or with inferred elements
1254
- }
1170
+ // Issue messages about dubious extensions ------------------------------------
1171
+ // checkXYZ() = return whether to extend, reportXYZ() = extend anyway
1255
1172
 
1256
-
1257
- // console.log(message( 'id', [ext.location, ext], { art: ext.name._artifact },
1258
- // 'Info', 'EXT').toString())
1259
- setArtifactLink( ext.name, art ); // TODO: probably already done
1260
- if (ext.includes)
1261
- applyIncludes( ext, art ); // moves included elem to extension(! TODO: recheck)
1262
- else if (ext.elements)
1263
- art.$postponeInclude += addedElements( ext );
1264
-
1265
- // console.log(ext,art)
1266
- checkAnnotate( ext, art );
1267
- // TODO: do we allow to add elements with array of {...}? If yes, adapt
1268
- initMembers( ext, art, ext._block ); // might set _extend, _annotate
1269
- dependsOnSilent( art, ext ); // art depends silently on ext (inverse to normal dep!)
1270
-
1271
- for (const name in ext.elements) {
1272
- const elem = ext.elements[name];
1273
- if (elem.kind === 'element') { // i.e. not extend or annotate
1274
- elemExtensions.push( elem );
1275
- break; // more than one elem in same EXTEND is fine
1173
+ // called from extendArtifactAfter()
1174
+ function checkExtensionDictionary( ext, art, artProp, extProp ) {
1175
+ if (art.kind === 'annotate') // the super annotate
1176
+ return true;
1177
+ // assume dict not on art
1178
+ const dict = ext[extProp];
1179
+ const location = dict?.[$location] ||
1180
+ dictFirst( dict )?.name?.location || // for `annotate E:elem`
1181
+ ext.name.location;
1182
+ switch (artProp) {
1183
+ case 'params':
1184
+ // currently just via `annotate`, TODO: test w/ CSN input
1185
+ warning( 'anno-unexpected-params', [ location, ext ], {},
1186
+ 'Parameters only exist for actions or functions' );
1187
+ // TODO text: or query entities
1188
+ break;
1189
+ case 'actions':
1190
+ // extendArtifactAdd() had created actions prop with correct actions extensions
1191
+ if (ext.kind === 'extend' && Object.keys( dict ).length) {
1192
+ error( 'def-unexpected-actions', [ location, ext ], {}, // TODO: ext-
1193
+ 'Actions and functions only exist top-level and for entities' ); // or aspects
1194
+ }
1195
+ else { // annotate or empty dict
1196
+ warning( 'ext-ignoring-actions', [ location, ext ], {},
1197
+ 'Actions and functions only exist top-level and for entities' );
1198
+ return true;
1199
+ }
1200
+ break;
1201
+ case 'elements':
1202
+ if (ext.kind === 'annotate') {
1203
+ warning( 'anno-unexpected-elements', [ location, ext ],
1204
+ { '#': art.type?._artifact?.kind } );
1205
+ // extra msg variant for entity as parameter type
1206
+ }
1207
+ else if (ext.kind === 'extend' && Object.keys( dict ).length) {
1208
+ // TODO v8: also error with empty dict
1209
+ const msgid = [ 'type', 'aspect' ].includes( art.kind )
1210
+ ? 'extend-type'
1211
+ : 'def-unexpected-elements';
1212
+ error( msgid, [ location, ext ], {} );
1213
+ }
1214
+ else { // annotate or empty dict
1215
+ warning( 'ext-ignoring-elements', [ location, ext ], {},
1216
+ 'Only structures with directly specified elements can be extended by elements' );
1217
+ return true;
1218
+ }
1219
+ break;
1220
+ case 'enum':
1221
+ if (ext.kind === 'extend') {
1222
+ const msgid = art.kind === 'type' ? 'extend-type' : 'def-unexpected-enum';
1223
+ error( msgid, [ location, ext ], {} );
1276
1224
  }
1225
+ break;
1226
+ case 'foreignKeys': {
1227
+ // currently just via `annotate`
1228
+ warning( 'ext-undefined-key', [ location, ext ], { '#': 'dict' } );
1229
+ break;
1277
1230
  }
1231
+ default:
1232
+ if (model.options.testMode)
1233
+ throw new CompilerAssertion(`Missing case for prop: ${ artProp }`);
1278
1234
  }
1279
- if (elemExtensions.length > 1)
1280
- reportUnstableExtensions( elemExtensions ); // TODO: still?
1235
+ return ext.kind === 'annotate';
1236
+ // Remark: to detect security-relevant annotation on (sub) members,
1237
+ // super-annotates must be created (→ return true) when no error is reported.
1238
+ }
1281
1239
 
1282
- // This whole function will be removed with a next change - no need to have nice code here:
1283
- const dict = Object.create( null );
1284
- // actions cannot be extended anyway. TODO: there should be a message
1285
- // (possible with CSN input), but that was missing before this change, too.
1286
- for (const e of extensions) {
1287
- if (!e.elements)
1288
- continue;
1289
- for (const n in e.elements) {
1290
- if (e.elements[n].kind === 'extend')
1291
- pushToDict( dict, n, e.elements[n] );
1292
- }
1293
- }
1294
- for (const name in dict) {
1295
- let obj = art;
1296
- if (obj.targetAspect)
1297
- obj = obj.targetAspect;
1298
- while (obj.items)
1299
- obj = obj.items;
1300
- const validDict = obj.elements || obj.enum;
1301
- const member = validDict && validDict[name];
1302
- if (!member)
1303
- extendNothing( dict[name], 'elements', name, art, validDict );
1304
- }
1240
+ function reportDuplicate( name, location, art ) {
1241
+ if (art.$duplicates) // already reported in define.js
1242
+ return;
1243
+ error( 'duplicate-definition', [ art.name.location, art ], {
1244
+ name: art.name.id,
1245
+ '#': kindProperties[art.kind].normalized || art.kind,
1246
+ } );
1305
1247
  }
1306
1248
 
1307
- /**
1308
- * Report 'Warning: Unstable element order due to repeated extensions'
1309
- * except if all extensions are in the same file.
1310
- *
1311
- * @param {XSN.Extension[]} extensions
1312
- */
1313
- function reportUnstableExtensions( extensions ) {
1314
- // No message if all extensions are in the same file:
1315
- const file = layers.realname( extensions[0] );
1316
- if (extensions.every( ( ext, i ) => !i || file === layers.realname( ext ) ))
1249
+ function reportUnexpectedMemberExtensions( parent, ext, prop, name ) {
1250
+ const securityRelevant = hasSecurityAnno( ext ) ? '-sec' : '';
1251
+ const dict = (parent.kind === 'annotate') ? null : parent[prop];
1252
+ // real dictionary, not just one in the super-annotate
1253
+
1254
+ // checkExtensionDictionary() had complained about extension with unexpected
1255
+ // dict property → new message just for missing art member (or if security
1256
+ // relevant)
1257
+ if (dict ? dict[name] : !securityRelevant)
1317
1258
  return;
1318
- // Similar to chooseAssignment(), TODO there: also extra intralayer message
1319
- // as this is a modeling error
1320
- let lastExt = null;
1321
- let open = []; // the "highest" layers
1322
- for (const ext of extensions) {
1323
- const extLayer = layers.layer( ext ) ||
1324
- { realname: '', _layerExtends: Object.create( null ) };
1325
- if (!open.length) {
1326
- lastExt = ext;
1327
- open = [ extLayer.realname ];
1328
- }
1329
- else if (extLayer.realname === open[open.length - 1]) { // in same layer
1330
- if (lastExt) {
1331
- message( 'extend-repeated-intralayer', [ lastExt.location, lastExt ] );
1332
- lastExt = null;
1333
- }
1334
- message( 'extend-repeated-intralayer', [ ext.location, ext ] );
1259
+
1260
+ // Remark: there can currently be just an extend in elements/enum, not actions etc
1261
+ switch (prop) {
1262
+ case 'elements':
1263
+ case 'enum': {
1264
+ if (ext.kind === 'annotate' && parent.kind === 'entity' &&
1265
+ canBeDraftMember( name, parent, draftElements ))
1266
+ break;
1267
+ const msgId = (ext.kind === 'extend')
1268
+ ? 'extend-undefined'
1269
+ : `ext-undefined-element${ securityRelevant }`;
1270
+ // eslint-disable-next-line no-nested-ternary
1271
+ const msgVn = (!parent._parent?.returns)
1272
+ ? prop
1273
+ : (prop === 'enum' ? 'enum-returns' : 'returns');
1274
+ notFound( msgId, ext.name.location, ext,
1275
+ { '#': msgVn, name, art: parent },
1276
+ dict );
1277
+ break;
1335
1278
  }
1336
- else {
1337
- if (lastExt && (open.length > 1 || !extLayer._layerExtends[open[0]])) {
1338
- // report for lastExt if that is unrelated to other open exts or current ext
1339
- message( 'extend-unrelated-layer', [ lastExt.location, lastExt ], {},
1340
- 'Unstable element order due to other extension in unrelated layer' );
1341
- }
1342
- lastExt = ext;
1343
- open = open.filter( name => !extLayer._layerExtends[name] );
1344
- open.push( extLayer.realname );
1279
+ case 'foreignKeys': {
1280
+ notFound( `ext-undefined-key${ securityRelevant }`, ext.name.location, ext,
1281
+ { name }, parent.foreignKeys );
1282
+ break;
1345
1283
  }
1284
+ case 'params':
1285
+ notFound( `ext-undefined-param${ securityRelevant }`, ext.name.location, ext,
1286
+ { '#': 'param', name },
1287
+ dict );
1288
+ break;
1289
+ case 'actions':
1290
+ if (ext.kind === 'annotate' && parent.kind === 'entity' &&
1291
+ canBeDraftMember( name, parent, draftBoundActions ))
1292
+ break;
1293
+ notFound( `ext-undefined-action${ securityRelevant }`, ext.name.location, ext,
1294
+ { '#': 'action', name },
1295
+ dict );
1296
+ break;
1297
+ default:
1298
+ if (model.options.testMode)
1299
+ throw new CompilerAssertion(`Missing case for prop: ${ prop }`);
1346
1300
  }
1347
1301
  }
1348
1302
 
1349
-
1350
1303
  /**
1351
- * @param {XSN.Extension[]} extensions
1352
- * @param {string} prop
1353
- * @param {string} name
1354
- * @param {XSN.Artifact} art
1355
- * @param {object} validDict
1304
+ * Complain about invalid `extend service` and `extend context`.
1305
+ * Called in extendArtifactBefore().
1356
1306
  */
1357
- function extendNothing( extensions, prop, name, art, validDict ) {
1358
- // TODO: probably too much magic in the creation of artName…
1359
- const extMain = { ...(art._main || art) };
1360
- const artName = searchName( art, name, dictKinds[prop] );
1361
- setLink( artName, '_main', extMain );
1307
+ function reportInvalidExtensionKind( extensions, art ) {
1362
1308
  for (const ext of extensions) {
1363
- // TODO: use shared functionality with notFound in resolver.js
1364
- const { location } = ext.name;
1365
- extMain.kind = ext.kind;
1366
- const msg = error( 'extend-undefined', [ location, artName ], { art: artName }, {
1367
- std: 'Unknown $(ART) - nothing to extend',
1368
- element: 'Artifact $(ART) has no element or enum $(MEMBER) - nothing to extend',
1369
- action: 'Artifact $(ART) has no action $(MEMBER) - nothing to extend',
1370
- } );
1371
- attachAndEmitValidNames( msg, validDict );
1372
- }
1373
- }
1374
-
1375
- // TODO TMP: copied from ./define.js: -----------------------------------------
1376
-
1377
- /**
1378
- * Set property `_parent` for all elements in `parent` to `parent` and do so
1379
- * recursively for all sub elements.
1380
- *
1381
- * If `construct !== parent`, also copy elements to `parent`.
1382
- *
1383
- * (Only) if called recursively: `construct === parent`
1384
- *
1385
- * TODO: separate extension!
1386
- */
1387
- function initMembers( construct, parent, block ) {
1388
- // only called by extendMembers() and recursively
1389
- // TODO: split extend from init
1390
- const obj = initItemsLinks( construct, block );
1391
- initExprAnnoBlock( construct, block, error );
1392
- if (parent.targetAspect?.elements)
1393
- parent = parent.targetAspect;
1394
- const main = parent._main || parent;
1395
- const isQueryExtension = construct.kind === 'extend' && main.query;
1396
-
1397
- if (obj !== parent && obj.elements && parent.enum) { // applying the extension
1398
- initElementsAsEnum();
1399
- if (parent.enum[$inferred])
1400
- setExpandStatus( parent, 'extend' );
1401
- }
1402
- else {
1403
- if (checkDefinitions( construct, parent, 'elements', obj.elements || false ))
1404
- forEachInOrder( obj, 'elements', init );
1405
- if (checkDefinitions( construct, parent, 'enum', obj.enum || false ))
1406
- forEachGeneric( obj, 'enum', init );
1407
- }
1408
-
1409
- if (obj.foreignKeys)
1410
- forEachInOrder( obj, 'foreignKeys', init );
1411
- if (checkDefinitions( construct, parent, 'actions' ))
1412
- forEachGeneric( construct, 'actions', init );
1413
- if (checkDefinitions( construct, parent, 'params' ))
1414
- forEachInOrder( construct, 'params', init );
1415
- const { returns } = construct;
1416
- if (returns) {
1417
- const { kind } = construct;
1418
- returns.kind = (kind === 'extend' || kind === 'annotate') ? kind : 'param';
1419
- init( returns, '' ); // '' is special name for returns parameter
1420
- }
1421
- return;
1422
-
1423
- // We allow `extend MyEnum with {…}` and not just `extend MyEnum with enum {…}`
1424
- // for compatibility, with a warning.
1425
- function initElementsAsEnum() {
1426
- // in extensions, extended enums are represented as elements
1427
- let hasElement = false;
1428
- for (const n in obj.elements) {
1429
- const e = obj.elements[n];
1430
- if (e.kind === 'extend')
1431
- continue;
1432
- if (e.$syntax !== 'or-enum') { // parser might set $syntax: 'or-enum'
1433
- // We do not want to complain separately about all element properties:
1434
- error( 'ext-unexpected-element', [ e.location, construct ],
1435
- { name: e.name.id, code: 'extend … with enum' },
1436
- // eslint-disable-next-line @stylistic/max-len
1437
- 'Unexpected elements like $(NAME) in an extension for an enum. Additionally, use $(CODE) when extending enums' );
1438
- // Don't emit 'ext-expecting-enum' if this error is emitted.
1439
- return;
1309
+ const kind = ext.expectedKind?.val;
1310
+ if (kind && kind !== art.kind) {
1311
+ const loc = ext.expectedKind.location;
1312
+ if (kind === 'context' || kind === 'service') {
1313
+ // We have no real artifact during the construction of a super-annotate statement:
1314
+ const msgArgs = {
1315
+ '#': (art.kind === 'service' || art.kind === 'annotate') ? art.kind : 'std',
1316
+ art,
1317
+ kind,
1318
+ code: 'extend … with definitions',
1319
+ keyword: 'extend service',
1320
+ };
1321
+ // TODO v7: Discuss: make this an error?
1322
+ warning( 'ext-invalid-kind', [ loc, ext ], msgArgs, {
1323
+ std: 'Artifact $(ART) is not of kind $(KIND), use $(CODE) instead',
1324
+ annotate: 'There is no artifact $(ART), use $(CODE) instead',
1325
+ // do not mention 'extend context', that is not in CAPire
1326
+ service: 'Artifact $(ART) is not of kind $(KIND), use $(CODE) or $(KEYWORD) instead',
1327
+ } );
1440
1328
  }
1441
- e.kind = 'enum';
1442
- hasElement = true; // warning with CDL input or `name: {}` in CSN input
1443
- }
1444
- if (!parent.type || parent.type.$inferred || (parent._main || parent).query) {
1445
- error( 'extend-type', [ obj.elements[$location], construct ], {},
1446
- 'Only structures or enum types can be extended with elements/enums' );
1447
- }
1448
- else if (hasElement) {
1449
- warning( 'ext-expecting-enum', [ obj.elements[$location], construct ],
1450
- { code: 'extend … with enum' }, 'Use $(CODE) when extending enums' );
1329
+ // TODO: Use similar checks for EXTEND ENTITY etc - 'ext-ignoring-kind'
1451
1330
  }
1452
- forEachGeneric( { enum: obj.elements }, 'enum', init );
1453
1331
  }
1332
+ }
1454
1333
 
1455
- function init( elem, name, prop ) {
1456
- if (!elem.name && !elem._outer) {
1457
- const ref = elem.targetElement || elem.kind === 'element' && elem.value;
1458
- if (ref && ref.path) {
1459
- elem.name = Object.assign( { $inferred: 'as' },
1460
- ref.path[ref.path.length - 1] );
1461
- }
1462
- else { // RETURNS, parser robustness
1463
- elem.name = { id: name, location: elem.location };
1334
+ // called in createSuperAnnotate()
1335
+ function reportExtensionOnBuiltin( art, ext ) {
1336
+ const refCtx = extensionRefContext( ext );
1337
+ if (resolvePath( ext.name, refCtx, ext ) && art?.builtin) {
1338
+ if (ext.kind === 'extend') {
1339
+ // extending built-ins with elements/enums already gives an error
1340
+ message( 'ext-unexpected-builtin', [ ext.name.location, ext ], {},
1341
+ 'Built-in types should not be extended' ); // keep the text general
1342
+ // TODO v8: error - especially bad with includes extension
1343
+ const typeProp = typeParameters.list.find( p => ext[p] );
1344
+ if (typeProp) {
1345
+ const location = ext.$typeArgs?.[$location] || ext[typeProp].location;
1346
+ message( 'ext-unexpected-type-property', [ location, ext ], {}, // error v7
1347
+ 'Built-in types can\'t be extended with type properties' );
1348
+ // see also 'ext-invalid-type-property'
1464
1349
  }
1465
1350
  }
1466
-
1467
- if (!elem._block)
1468
- setLink( elem, '_block', block );
1469
- // if (!kindProperties[ elem.kind ]) console.log(elem.kind,elem.name)
1470
- if ((elem.kind === 'extend' || elem.kind === 'annotate'))
1471
- return;
1472
-
1473
- if (isQueryExtension && elem.kind === 'element') {
1474
- error( 'extend-query', [ elem.location, construct ], // TODO: searchName ?
1475
- { code: 'extend … with columns' },
1476
- 'Use $(CODE) to add select items to the query entity' );
1477
- return;
1478
- }
1479
-
1480
- const existing = parent[prop]?.[name];
1481
- const shadowsIncludeMember = construct !== parent &&
1482
- elem.$inferred !== 'include' &&
1483
- existing?.$inferred === 'include';
1484
- const add = construct !== parent && (!existing || elem.$inferred !== 'include');
1485
- if (!add && existing?.$inferred === 'include' && elem.$inferred === 'include') {
1486
- includeCollisions.push( {
1487
- prop, name, existing, elem,
1488
- } );
1489
- }
1490
- // don't dump with `entity T {}; extend T with { extend e {}; e {}; e {} };`:
1491
- const { $duplicates } = elem;
1492
- if ($duplicates === true && add)
1493
- elem.$duplicates = null;
1494
- if (add && elem.$inferred === 'include' && Array.isArray( $duplicates ))
1495
- elem.$duplicates = null;
1496
- if (shadowsIncludeMember) {
1497
- parent[prop][name] = elem;
1498
- setMemberParent( elem, name, parent );
1499
- }
1500
1351
  else {
1501
- setMemberParent( elem, name, parent, add && prop );
1502
- if (!$duplicates) // not already reported
1503
- checkRedefinition( elem );
1352
+ info( 'anno-builtin', [ ext.name.location, ext ], {} ); // TODO: better location?
1504
1353
  }
1505
- initMembers( elem, elem, elem._block );
1506
- if (elem.kind === 'action' || elem.kind === 'function')
1507
- initBoundSelfParam( elem.params, elem._main );
1354
+ // TODO: remove built-ins as CC candidates via accept property of ./shared.js
1355
+ }
1356
+ }
1508
1357
 
1509
- // for a correct home path, setMemberParent needed to be called
1358
+ // Called in extendArtifactAdd()
1359
+ function reportExtensionOnGenerated( ext, art, prop, extMembers ) {
1360
+ // Beware: if we allow element extensions later, we might still want to
1361
+ // disallow includes with elements, see reportInvalidIncludes(); additionally,
1362
+ // adding sub elements might still be wrong
1363
+ const location = ext[prop]?.[$location] || ext.name.location;
1364
+ if (ext.enum) { // enum extension on structure
1365
+ error( 'def-unexpected-enum', [ location, ext ], {} );
1366
+ }
1367
+ else if (art.$inferred === 'include') { // element of include
1368
+ error( 'ref-expected-direct-structure', [ location, ext ],
1369
+ { '#': 'elements', art } );
1370
+ }
1371
+ else if (extMembers && Object.keys( extMembers ).length ||
1372
+ ext.includes?.some( ref => dictNonEmpty( ref._artifact.elements ))) {
1373
+ // TODO: we could allow extMembers containing `extend`s only, but then make
1374
+ // sure that we do not accidentially allow adding sub elements
1375
+ error( 'extend-for-generated', [ location, ext ],
1376
+ { // eslint-disable-next-line no-nested-ternary
1377
+ '#': (art.query ? 'query' : ext.includes ? 'std' : prop),
1378
+ art,
1379
+ keyword: 'extend',
1380
+ }, {
1381
+ std: 'You can\'t use $(KEYWORD) on the generated $(ART)',
1382
+ query: 'You can\'t use $(KEYWORD) on the query to add elements',
1383
+ elements: 'You can\'t use $(KEYWORD) on the inferred elements of $(ART)',
1384
+ } );
1385
+ // TODO: for invalid includes, use specific ref-invalid-include messages
1386
+ }
1387
+ }
1510
1388
 
1511
- if (parent[prop]?.[$inferred])
1512
- setExpandStatus( parent, 'extend' );
1389
+ // Remark: the acceptFn for resolvePath() does a first check whether includes
1390
+ // are allowed
1391
+ function reportInvalidIncludes( art ) {
1392
+ const { elements } = art;
1393
+ for (const ref of art.includes) {
1394
+ const incl = ref._artifact;
1395
+ if (!incl)
1396
+ continue;
1397
+ if (!elements && (incl.elements || incl.kind !== 'aspect'))
1398
+ error( 'ref-invalid-include', [ ref.location, art ], { '#': 'bare' } );
1399
+ else if ((incl.elements ? incl.elements[$inferred] : incl.kind !== 'aspect') ||
1400
+ incl.query) // TODO: allow query entity and inferred elems soon
1401
+ error( 'ref-invalid-include', [ ref.location, art ] );
1402
+ }
1403
+ }
1513
1404
 
1514
- if (!elem.value || elem.kind !== 'element')
1515
- return;
1516
- // remark: potential enum elements have already been turned into enums
1517
- // -> it's a calculated element
1518
- if (!elem.type && elem.value?.type) { // top-level CAST( expr AS type )
1519
- if (!elem.target)
1520
- elem.type = { ...elem.value.type, $inferred: 'cast' };
1521
- }
1522
- elem.$syntax = 'calc';
1523
- // TODO: it is not just "syntax" - maybe better test for `$calcDepElement`?
1524
- createAndLinkCalcDepElement( elem );
1525
-
1526
- // Special case (hack) for calculated elements that use composition+filter:
1527
- // See "Notes on `$enclosed`" in `ExposingAssocWithFilter.md` for details.
1528
- if (elem.target && elem.value.path?.[elem.value.path.length - 1]?.where) {
1529
- delete elem.type;
1530
- delete elem.on;
1531
- delete elem.target;
1405
+ // Called in extendArtifactAdd()
1406
+ function reportTypeIncludesWithActions( art ) {
1407
+ for (const ref of art.includes || []) {
1408
+ const incl = ref._artifact;
1409
+ if (incl?.actions && Object.keys( incl.actions ).length) {
1410
+ warning( 'ref-ignoring-actions', [ ref.location, art ], { art: incl },
1411
+ 'The actions of $(ART) are not added to the type' ); // TODO: info?
1532
1412
  }
1533
1413
  }
1534
1414
  }
1535
1415
 
1536
- // TODO: is only necessary for extensions - make special for extend/annotate
1537
- function checkDefinitions( construct, parent, prop, dict = construct[prop] ) {
1538
- // TODO: do differently, see also annotateMembers() in resolver
1539
- // To have been checked by parsers:
1540
- // - artifacts (CDL-only anyway) only inside [extend] context|service
1541
- if (!dict)
1542
- return false;
1543
- const feature = kindProperties[parent.kind ?? 'element'][prop];
1544
- if (feature &&
1545
- (feature === true || construct.kind !== 'extend' || feature( prop, parent )))
1546
- return true;
1547
- const location = dict[$location];
1416
+ // Called in extendArtifactBefore() and extendArtifactAfter()
1417
+ function reportUnexpectedReturns( ext, art ) {
1418
+ const msgId = hasSecurityAnno( ext.returns )
1419
+ ? 'ext-unexpected-returns-sec'
1420
+ : 'ext-unexpected-returns';
1421
+ message( msgId, [ ext.returns.location, ext ],
1422
+ { '#': art.kind, keyword: 'returns' } );
1423
+ }
1548
1424
 
1549
- // TODO: a bit inconsistent = not a simple switch on `prop`…
1550
- if (prop === 'actions') {
1551
- if (Object.keys( dict ).length) {
1552
- error( 'def-unexpected-actions', [ location, construct ], {}, // TODO: ext-
1553
- 'Actions and functions only exist top-level and for entities' ); // or aspects
1554
- }
1555
- else {
1556
- warning( 'ext-ignoring-actions', [ location, construct ], {},
1557
- 'Actions and functions only exist top-level and for entities' );
1558
- return false;
1559
- }
1560
- }
1561
- else if (parent.kind === 'action' || parent.kind === 'function') {
1562
- error( 'ext-unexpected-action', [ construct.location, construct ], { '#': parent.kind }, {
1425
+ // Called in extendArtifactAfter()
1426
+ function reportMissingReturns( ext, art ) {
1427
+ if (ext.kind === 'extend') {
1428
+ error( 'ext-unexpected-action', [ ext.name.location, ext ], { '#': art.kind }, {
1563
1429
  std: 'Actions and functions can\'t be extended, only annotated', // TODO: → ext-unsupported
1564
1430
  action: 'Actions can\'t be extended, only annotated',
1565
1431
  function: 'Functions can\'t be extended, only annotated',
1566
1432
  } );
1567
1433
  }
1568
- else if (prop === 'params') {
1569
- if (!feature) {
1570
- // Note: This error can't be triggered at the moment. But as we likely want to
1571
- // allow extensions with params in the future, we keep the code.
1572
- error( 'def-unexpected-params', [ location, construct ], {},
1573
- 'Parameters only exist for entities, actions or functions' );
1574
- }
1575
- else {
1576
- // remark: we could allow this
1577
- error( 'extend-with-params', [ location, construct ], {},
1578
- 'Extending artifacts with parameters is not supported' );
1579
- }
1580
- }
1581
- else if (feature) { // allowed in principle, but not with extend
1582
- if (!Object.keys( dict ).length) {
1583
- warning( 'ext-ignoring-elements', [ location, construct ], {},
1584
- 'Only structures with directly specified elements can be extended by elements' );
1585
- return false;
1586
- }
1587
- else if (parent.$inferred === 'include') { // special case for better error message
1588
- const variant = (construct.enum || construct.elements) ? 'elements' : 'std';
1589
- error( 'ref-expected-direct-structure', [ location, construct ],
1590
- { '#': variant, art: parent } );
1591
- }
1592
- else if (prop !== 'enum' || !parent.enum ||
1593
- !parent.type || parent.type.$inferred || (parent._main || parent).query) {
1594
- error( 'extend-type', [ location, construct ], {},
1595
- 'Only structures or enum types can be extended with elements/enums' );
1596
- }
1597
- else {
1598
- return true;
1599
- }
1600
- }
1601
- else if (prop === 'elements') {
1602
- error( 'def-unexpected-elements', [ location, construct ], {},
1603
- 'Elements only exist in entities, types or typed constructs' );
1604
- }
1605
- else if (prop === 'columns') {
1606
- error( 'extend-columns', [ location, construct ], { art: construct } );
1607
- }
1608
- else { // if (prop === 'enum') {
1609
- error( 'def-unexpected-enum', [ location, construct ], {},
1610
- 'Enum symbols can only be defined for types or typed constructs' );
1434
+ else {
1435
+ warning( 'ext-expecting-returns', [ ext.name.location, ext ], {
1436
+ '#': art.kind, keyword: 'returns', code: 'annotate ‹name› with returns { … }',
1437
+ }, {
1438
+ std: 'Expected $(CODE)', // unused variant
1439
+ action: 'Expected $(KEYWORD) when annotating action return structure, i.e. $(CODE)',
1440
+ function: 'Expected $(KEYWORD) when annotating function return structure, i.e. $(CODE)',
1441
+ // eslint-disable-next-line @stylistic/max-len
1442
+ annotate: 'Expected $(KEYWORD) when annotating a return structure of an unknown action or function, i.e. $(CODE)',
1443
+ } );
1611
1444
  }
1612
- return construct === parent;
1613
1445
  }
1614
1446
 
1615
-
1616
- // includes ----------------------------------------------------------------
1617
-
1618
1447
  /**
1619
- * Apply all includes of `ext` on `ext`. Checks that `art` allows includes.
1620
- * If `ext === art`, then includes of the artifact itself are applied.
1621
- * If `ext !== art`, applies includes on the extensions, not artifact.
1622
-
1623
- * Sets `_ancestors` links on `art` if it is an entity, collecting the entity
1624
- * includes with their ancestors.
1625
- *
1626
- * Examples:
1627
- * ext === art: `entity E : F {}` => add elements of F to E
1628
- * ext !== art: `extend E with F` => add elements of F to extension on E
1629
- *
1630
- * @param {XSN.Extension} ext
1631
- * @param {XSN.Artifact} art
1448
+ * Report duplicates in parent[prop] that happen due to multiple includes having
1449
+ * the same member. Run after includes and extends in extendArtifactAdd() so
1450
+ * shadowing members have already replaced any include-derived proxy.
1632
1451
  */
1633
- function setEntityIncludes( ext, art ) {
1634
- setLink( art, '_entityIncludes', [] );
1635
- for (const ref of ext.includes) {
1636
- const name = resolveUncheckedPath( ref, 'include', ext );
1637
- const template = name && model.definitions[name];
1638
- if (template?.kind === 'entity')
1639
- art._entityIncludes.push( template );
1640
- }
1452
+ function reportRedefinitionThroughIncludes( parent, prop ) {
1453
+ if (!parent[prop])
1454
+ return;
1455
+ forEachInOrder( parent, prop, ( member, name ) => {
1456
+ if (member.$inferred === 'include' && Array.isArray( member.$duplicates )) {
1457
+ const includes = [ member, ...member.$duplicates ].map( dup => dup._origin._main );
1458
+ // TODO: 'ref-duplicate-include-member' with one message per affected include,
1459
+ // mentioning the problematic element/action names
1460
+ error( 'duplicate-definition', [ member.location, member ],
1461
+ { '#': `include-${ prop }`, name, sorted_arts: includes } );
1462
+ }
1463
+ } );
1641
1464
  }
1642
1465
 
1643
- function applyIncludes( ext, art ) {
1644
- if (kindProperties[art.kind].include !== true) {
1645
- error( 'extend-unexpected-include', [ ext.includes[0]?.location, ext ],
1646
- { meta: art.kind } );
1647
- return;
1466
+ // TODO: still a bit annotation assignment specific
1467
+ // Called in extendArtifactBefore().
1468
+ function reportDuplicateExtensions( extensions, prop, issue, index, art ) {
1469
+ // TODO: think about messages for these
1470
+ if (prop === 'elements' || prop === 'actions' || prop === 'columns' ||
1471
+ prop === 'params' || prop === '$add' ) {
1472
+ if (issue && (prop === '$add' || prop === 'columns'))
1473
+ reportUnstableExtensions( extensions, issue );
1474
+ return; // extensions currently handled extra
1648
1475
  }
1649
- // console.log( (ext===art?'D-INCL:':'E-INCL:'), art.kind, art.name.id,
1650
- // ...ext.includes.map( r => r._artifact?.name.id ));
1651
- if (!art.query && art.elements) // do not set art.elements and art.enums with query entity!
1652
- includeMembers( ext, art, 'elements' );
1653
1476
 
1654
- if (art.kind !== 'type') {
1655
- includeMembers( ext, art, 'actions' );
1656
- }
1657
- else {
1658
- for (const ref of ext.includes) {
1659
- const template = ref._artifact; // already resolved
1660
- if (template?.actions && Object.keys( template.actions ).length) {
1661
- warning( 'ref-ignoring-actions', [ ref.location, ext ], { art: template },
1662
- 'The actions of $(ART) are not added to the type' );
1477
+ const isTypeParam = typeParameters.list.includes( prop );
1478
+ const isAnnoOrDoc = prop.charAt(0) === '@' || prop === 'doc';
1479
+ if (!isAnnoOrDoc && !isTypeParam && prop !== 'orderBy')
1480
+ return;
1481
+ if (issue) {
1482
+ if (prop === 'orderBy' && issue === 'unrelated') {
1483
+ for (const ext of extensions) {
1484
+ const clause = ext[prop];
1485
+ if (clause) {
1486
+ message( 'ext-unstable-order', [ clause[0]?.location || ext.location, ext ],
1487
+ { keyword: prop },
1488
+ // eslint-disable-next-line @stylistic/max-len
1489
+ 'Unstable order of entries in the $(KEYWORD) clause due to another extension in unrelated layer' );
1490
+ }
1491
+ }
1492
+ return;
1493
+ }
1494
+ if (isAnnoOrDoc && prop !== 'doc' &&
1495
+ allAnnoValuesEqual( extensions, prop )) {
1496
+ if (issue === 'unrelated')
1497
+ return;
1498
+ for (const ext of extensions) {
1499
+ const anno = ext[prop];
1500
+ if (anno) {
1501
+ // annotations with equal value in the same layer -> warn
1502
+ warning( 'anno-duplicate-equal', [ anno.name?.location || anno.location, ext ],
1503
+ { '#': 'std', anno: prop, type: art } );
1504
+ }
1505
+ }
1506
+ return;
1507
+ }
1508
+ // eslint-disable-next-line no-nested-ternary
1509
+ let msg = (index < 0)
1510
+ ? 'anno-unstable-array'
1511
+ : (issue === true)
1512
+ ? 'anno-duplicate'
1513
+ : 'anno-duplicate-unrelated-layer';
1514
+ if (prop === 'includes') {
1515
+ msg = (issue === true)
1516
+ ? 'ext-duplicate-includes'
1517
+ : 'ext-unstable-includes';
1518
+ // TODO v7: location on include would be nicer
1519
+ }
1520
+ else if (!isAnnoOrDoc) {
1521
+ msg = (issue === true)
1522
+ ? 'ext-duplicate-extend-type'
1523
+ : 'ext-duplicate-extend-type-unrelated-layer';
1524
+ // not sure whether to repeat the extended artifact in the message (we
1525
+ // have the semantic location, after all)
1526
+ // extend-repeated-intralayer / extend-unrelated-layer
1527
+ }
1528
+ const variant = prop === 'doc' ? 'doc' : 'std';
1529
+ for (const ext of extensions) {
1530
+ const anno = ext[prop];
1531
+ if (anno) {
1532
+ message( msg, [ anno.name?.location || anno.location, ext ],
1533
+ { '#': variant, anno: prop, type: art } );
1663
1534
  }
1664
1535
  }
1665
1536
  }
1537
+ else if (index > 0) { // more than one set (not just ...)
1538
+ const variant = prop === 'doc' ? 'doc' : 'std';
1539
+ const msgid = (isAnnoOrDoc)
1540
+ ? 'anno-duplicate-same-file' // TODO: always ext-duplicate-…
1541
+ : 'ext-duplicate-same-file';
1542
+ while (index >= 0) { // do not report for trailing [...]
1543
+ const ext = extensions[index--];
1544
+ const anno = ext[prop];
1545
+ warning( msgid, [ anno.name?.location || anno.location, ext ],
1546
+ { '#': variant, prop, anno: prop } );
1547
+ }
1548
+ }
1666
1549
  }
1667
1550
 
1668
1551
  /**
1669
- * Add all members (e.g. elements or actions) of `ext.includes` to `ext[prop]`.
1670
- * If `art` is `ext`, set the parent link accordingly.
1552
+ * Report 'Warning: Unstable element order due to repeated extensions'
1553
+ * except if all extensions are in the same file.
1671
1554
  *
1672
- * @param {XSN.Extension} ext
1673
- * @param {XSN.Artifact} art
1674
- * @param {string} prop 'elements' or 'actions'
1555
+ * Called in extendArtifactBefore(), via reportDuplicateExtensions().
1675
1556
  */
1676
- function includeMembers( ext, art, prop ) {
1677
- // TODO two kind of messages:
1678
- // Error 'More than one include defines element "A"' (at include ref)
1679
- // Warning 'Overwrites definition from include "I" (at elem def)
1680
- const propagateKeys = art.kind !== 'type' || model.options.v6KeyPropagation;
1681
- const parent = ext === art && art;
1682
- const members = ext[prop];
1683
- // if (members)console.log( 'EXT:', prop, art.kind, art.name.id, ...Object.keys(members));
1684
- if (members) {
1685
- ext[prop] = Object.create( null );
1686
- ext[prop][$location] = members[$location];
1687
- }
1688
- let elementsAdded = 0;
1689
- let hasNewElement = false;
1690
- for (const ref of ext.includes) {
1691
- // Elements of include are added after previously provided elements:
1692
- if (prop === 'elements') {
1693
- if (ref.$postponeInclude == null) {
1694
- if (ref._artifact?.elements)
1695
- ref.$postponeInclude = art.$postponeInclude || 0;
1696
- }
1697
- else if (ref.$postponeInclude > 0 && members) {
1698
- let added = elementsAdded;
1699
- let postpone = ref.$postponeInclude;
1700
- elementsAdded += postpone;
1701
- forEachInOrder( { [prop]: members }, prop, ( elem, name ) => {
1702
- // The element could have been added in the previous loop (includes) to keep
1703
- // the element order.
1704
- if (--added < 0 && --postpone >= 0 && ext[prop][name] !== elem )
1705
- dictAdd( ext[prop], name, elem );
1706
- } );
1707
- }
1708
- if (ref.$postponeInclude != null) // not reset after bare aspect
1709
- art.$postponeInclude = 0; // elements of next include directly after this one
1557
+ function reportUnstableExtensions( extensions, issue ) {
1558
+ for (const ext of extensions) {
1559
+ // TODO: location of complete includes / elements
1560
+ // (currently just for having lower diff in tests)
1561
+ const location = ext.includes?.[0]?.location ||
1562
+ ext.elements && Object.values( ext.elements )[0]?.location ||
1563
+ ext.columns?.[0]?.location ||
1564
+ ext.location;
1565
+ if (issue === 'unrelated') {
1566
+ message( 'extend-unrelated-layer', [ location, ext ], {},
1567
+ 'Unstable element order due to other extension in unrelated layer' );
1710
1568
  }
1711
- const template = ref._artifact; // already resolved
1712
- if (template) { // be robust
1713
- if (template[prop] && !ext[prop])
1714
- ext[prop] = Object.create( null );
1715
- const location = weakRefLocation( ref );
1716
-
1717
- // prevent recompilation issue when localized entity is included in aspect or
1718
- // entity without keys (via shadowing):
1719
- const checkForLocalized = prop === 'elements' &&
1720
- template.kind === 'entity' && !template.query &&
1721
- withLocalizedData( template, ext );
1722
-
1723
- // eslint-disable-next-line no-loop-func
1724
- forEachInOrder( template, prop, ( origin, name ) => {
1725
- if (checkForLocalized && (name === 'texts' || name === 'localized'))
1726
- return;
1727
- if (members && members[name]) {
1728
- if (!ext[prop][name])
1729
- dictAdd( ext[prop], name, members[name] ); // to keep order
1730
- return;
1731
- }
1732
- hasNewElement = true;
1733
- const elem = linkToOrigin( origin, name, parent, prop, location );
1734
- setLink( elem, '_block', origin._block );
1735
- if (!parent) // not yet set for EXTEND foo WITH bar => linkToOrigin() did not add it
1736
- dictAdd( ext[prop], name, elem );
1737
- elem.$inferred = 'include';
1738
- if (origin.key && propagateKeys)
1739
- elem.key = Object.assign( { $inferred: 'include' }, origin.key );
1740
- if (origin.value && origin.$syntax === 'calc') {
1741
- // TODO: If paths become invalid in the new artifact, should we mark
1742
- // all usages in the expressions? Possibly just the first one?
1743
- // TODO: Unify with other code in extend.js
1744
- elem.value = Object.assign( { $inferred: 'include' },
1745
- copyExpr( origin.value, location, true ) );
1746
- elem.$syntax = 'calc';
1747
- createAndLinkCalcDepElement( elem );
1748
- setLink( elem, '_calcOrigin', origin._calcOrigin || origin );
1749
- }
1750
- // TODO: also complain if elem is just defined in art
1751
- } );
1569
+ else {
1570
+ message( 'extend-repeated-intralayer', [ location, ext ] );
1752
1571
  }
1753
1572
  }
1754
- if (!hasNewElement && members) {
1755
- ext[prop] = members;
1756
- if (prop === 'elements')
1757
- art.$postponeInclude += addedElements( ext );
1758
- }
1759
- else if (members) {
1760
- let added = elementsAdded;
1761
- // TODO: expand elements having direct elements (if needed)
1762
- forEachInOrder( { [prop]: members }, prop, ( elem, name ) => {
1763
- // The element could have been added in the previous loop (includes) to keep
1764
- // the element order.
1765
- if (--added < 0 && ext[prop][name] !== elem ) {
1766
- dictAdd( ext[prop], name, elem );
1767
- if (prop === 'elements' && elem.kind !== 'extend')
1768
- ++art.$postponeInclude;
1769
- }
1770
- } );
1573
+ }
1574
+
1575
+ function allAnnoValuesEqual( extensions, prop ) {
1576
+ let first;
1577
+ let seen = false;
1578
+ for (const ext of extensions) {
1579
+ const anno = ext[prop];
1580
+ if (anno == null)
1581
+ continue;
1582
+ if (annotationHasEllipsis( anno ))
1583
+ return false;
1584
+ if (!seen) {
1585
+ first = anno;
1586
+ seen = true;
1587
+ }
1588
+ else if (!annoValueEqual( first, anno )) {
1589
+ return false;
1590
+ }
1771
1591
  }
1592
+ return seen;
1772
1593
  }
1773
1594
 
1774
- /**
1775
- * Return true if include (with `name` and `elements`) in `ext` highly likely
1776
- * contain elements `texts` and `localized` which are compiler-generated for
1777
- * localized data. Due to recompilation, we cannot just check the `$inferred`
1778
- * property in the XSN, but need to apply an heuristics.
1779
- * (We could still use $inferred as speed-up if run without `testMode`.)
1780
- *
1781
- * It is as follows: the elements `texts` and `localized` in entity `‹E›` and
1782
- * the entity `‹E›.texts` are considered compiler-generated for Localized Data if
1783
- *
1784
- * - `‹E›.texts` has a key element `locale`
1785
- * (TODO: currently weakend to “entity exists”)
1786
- * - `texts` of `‹E›` is an unmanaged composition to `‹E›.texts`
1787
- * - `localized` of `‹E›` is an unmanaged association to `‹E›.texts`
1788
- */
1789
- function withLocalizedData( { name, elements }, ext ) {
1790
- const textsEntityName = `${ name.id }.texts`;
1791
- // if we test (again) for element `locale` - it might come from an extend or
1792
- // TextsAspect include, which might not have yet applied
1793
- if (!model.definitions[textsEntityName])
1595
+ function annoValueEqual( a, b ) {
1596
+ if (a == null || b == null)
1597
+ return a == null && b == null;
1598
+ if (a.literal === 'array' || b.literal === 'array' ||
1599
+ a.path || b.path || a.struct || b.struct )
1794
1600
  return false;
1795
- const { texts, localized } = elements ?? {};
1796
- return texts?.target && localized?.target && texts.on && localized.on &&
1797
- resolveUncheckedPath( texts.target, 'target', ext ) === textsEntityName &&
1798
- resolveUncheckedPath( localized.target, 'target', ext ) === textsEntityName &&
1799
- resolveUncheckedPath( texts.type, 'type', ext ) === 'cds.Composition' &&
1800
- resolveUncheckedPath( localized.type, 'type', ext ) === 'cds.Association';
1601
+ if (a.sym || b.sym) {
1602
+ return a.literal === 'enum' && b.literal === 'enum' &&
1603
+ a.sym.id === b.sym.id;
1604
+ }
1605
+ if (!!a.$tokenTexts !== !!b.$tokenTexts)
1606
+ return false;
1607
+ if (a.$tokenTexts && !('val' in a && 'val' in b))
1608
+ return false;
1609
+ // no val (undefined) as true for annotation values
1610
+ const aVal = ('val' in a) ? a.val : true;
1611
+ const bVal = ('val' in b) ? b.val : true;
1612
+ const aLit = ('val' in a) ? a.literal : 'boolean';
1613
+ const bLit = ('val' in b) ? b.literal : 'boolean';
1614
+ return aVal === bVal && aLit === bLit;
1615
+ }
1616
+
1617
+ // TODO: in shared?
1618
+ function notFound( msgId, location, address, args, validDict ) {
1619
+ const msg = message( msgId, [ location, address ], args );
1620
+ attachAndEmitValidNames( msg, validDict );
1801
1621
  }
1802
1622
 
1623
+ // Foreign key extensions (currently postponed) -------------------------------
1624
+
1803
1625
  /**
1804
- * Report duplicates in parent[prop] that happen due to multiple includes having the
1805
- * same member. Run after includes and extends so shadowing members have already
1806
- * replaced any include-derived survivors in-place.
1626
+ * Apply foreign key extensions. Because foreign keys are handled late in the compiler
1627
+ * (in tweak-assocs.js), we can't apply them in effectiveType(), yet.
1628
+ * Instead, we postpone applying them until all foreign keys were generated.
1629
+ *
1630
+ * @param art
1807
1631
  */
1808
- function checkRedefinitionThroughIncludes( parent, prop ) {
1809
- if (!parent[prop])
1632
+ function extendForeignKeys( art ) {
1633
+ // See extendArtifactAfter() for targetAspect/items handling.
1634
+ if (!art._extensions || art.items || art.targetAspect?.elements)
1810
1635
  return;
1811
- forEachInOrder( parent, prop, ( member, name ) => {
1812
- if (member.$inferred === 'include' && Array.isArray( member.$duplicates )) {
1813
- const includes = [ member, ...member.$duplicates ].map( dup => dup._origin._main );
1814
- error( 'duplicate-definition', [ parent.name.location, member ],
1815
- { '#': `include-${ prop }`, name, sorted_arts: includes } );
1816
- }
1817
- } );
1636
+
1637
+ // push down foreign keys
1638
+ moveDictExtensions( art, art._extensions, 'foreignKeys', 'elements' );
1639
+ if (!art.foreignKeys)
1640
+ return;
1641
+
1642
+ forEachGeneric(art, 'foreignKeys', (key) => {
1643
+ if (!key._effectiveType)
1644
+ throw new CompilerAssertion( 'foreign key should have been processed' );
1645
+ extendArtifactBefore( key );
1646
+ // Adding foreign key not possible yet
1647
+ extendArtifactAfter( key );
1648
+ });
1818
1649
  }
1819
1650
  }
1820
1651
 
1652
+ // Utility functions ------------------------------------------------------------
1653
+
1654
+ function canBeDraftMember( name, parent, draftMembers ) {
1655
+ return parent?.kind === 'entity' && parent._service && draftMembers.includes( name );
1656
+ }
1657
+
1821
1658
  /**
1822
1659
  * Group extensions by their layers. A definition (for specified elements)
1823
1660
  * is considered to be provided in a layer named '', the lowest layer.
@@ -1915,6 +1752,7 @@ function compareExtensions( a, b ) {
1915
1752
  /**
1916
1753
  * Propagate the given `prop` (e.g. annotation) early, i.e. copy it from all `.includes`
1917
1754
  * if they have the property.
1755
+ * TODO: move to ./utils.js,
1918
1756
  *
1919
1757
  * @param {XSN.Definition} art
1920
1758
  * @param {string} prop