abapgit-agent 1.15.2 → 1.16.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.
@@ -36,8 +36,14 @@ The folder is configured in `.abapGitAgent` (property: `folder`):
36
36
 
37
37
  Each ABAP object needs an XML metadata file. Local helper/test-double classes use separate `.locals_def.abap` / `.locals_imp.abap` files.
38
38
 
39
+ **Name length limits** (verify before naming anything):
40
+ - CLAS, INTF: name **30 chars** | method names: **30 chars**
41
+ - TABL, STRU: name **30 chars** | **field names: 16 chars** ← most common mistake
42
+ - DDLS (CDS view entity): **40 chars** | field alias: 30 | FUGR: 26 | MSAG: 20 | PROG/DTEL/DOMA/TTYP: 30
43
+
39
44
  ```bash
40
- abapgit-agent ref --topic object-creation # XML templates and local class setup
45
+ abapgit-agent ref --topic naming-limits # full length reference
46
+ abapgit-agent ref --topic object-creation # XML templates and local class setup
41
47
  ```
42
48
 
43
49
  ### 4. Use Syntax Command Before Commit (for CLAS, INTF, PROG, DDLS)
@@ -65,6 +71,24 @@ abapgit-agent ref --topic debug-session # full debug guide
65
71
  abapgit-agent ref --topic debug-dump # dump analysis guide
66
72
  ```
67
73
 
74
+ ### 7. Never Run `run` Command Proactively
75
+
76
+ Never call `abapgit-agent run` unless the user explicitly asks — it can modify data or trigger RFCs.
77
+
78
+ ### 8. Probe and PoC Objects — Always Z/Y, Never in SAP Packages
79
+
80
+ When `objects.local.md` shows SAP namespace (`CL_*`, `IF_*`, `/NAMESPACE/*`) and the user asks to create a new object, always ask first: *"Is this a production object, a PoC, or a probe?"*
81
+
82
+ → `abapgit-agent ref --topic probe-poc`
83
+
84
+ ### 9. abaplint — Optional, Project-Controlled
85
+
86
+ Only run if `.abaplint.json` exists. Run after `syntax`, before commit. Always check `ref --topic abaplint` before applying any quickfix.
87
+
88
+ ```bash
89
+ ls .abaplint.json 2>/dev/null && abapgit-agent lint
90
+ ```
91
+
68
92
  ---
69
93
 
70
94
  ## Development Workflow
@@ -77,6 +101,8 @@ Checked into the repository — applies to all developers. **Read this file at t
77
101
  |---------|--------|
78
102
  | `safeguards.requireFilesForPull: true` | Always include `--files` in every `pull` |
79
103
  | `safeguards.disablePull: true` | Do not run `abapgit-agent pull` at all |
104
+ | `safeguards.disableRun: true` | Do not run `abapgit-agent run` at all |
105
+ | `safeguards.disableProbeClasses: true` | Use `scratchWorkspace` for probe classes instead |
80
106
  | `conflictDetection.mode: "abort"` | Abort pull on conflict — inform user |
81
107
  | `transports.allowCreate/allowRelease: false` | Blocked — inform user |
82
108
 
@@ -97,10 +123,15 @@ abapgit-agent ref --topic branch-workflow
97
123
  ```
98
124
  Modified ABAP files?
99
125
  ├─ CLAS/INTF/PROG/DDLS files?
100
- │ ├─ Independent files? → syntax → commit → push → pull
101
- │ └─ Dependent files? → skip syntax → commit → push → pull
126
+ │ ├─ Independent files? → syntax → [abaplint] → commit → push → pull --sync-xml
127
+ │ └─ Dependent files? → skip syntax → [abaplint] → commit → push → pull --sync-xml
102
128
  └─ Other types (FUGR, TABL, etc.)?
103
- skip syntax commit push → pull → (if errors: inspect)
129
+ ├─ XML-only (TABL, STRU, DTEL, TTYP, DOMA, MSAG)?
130
+ │ → skip syntax → [abaplint] → commit → push → pull --files <name>.tabl.xml --sync-xml
131
+ └─ FUGR and others?
132
+ → skip syntax → [abaplint] → commit → push → pull --sync-xml → (if errors: inspect)
133
+
134
+ [abaplint] = run lint only if .abaplint.json exists; ref --topic abaplint before any quickfix
104
135
  ```
105
136
 
106
137
  ```bash
package/abap/CLAUDE.md CHANGED
@@ -99,6 +99,20 @@ Never assume Z/Y prefix without checking.
99
99
  XML-only objects (TABL, STRU, DTEL, TTYP, DOMA, MSAG) need ONLY the XML file
100
100
  ```
101
101
 
102
+ **Before choosing a name, verify the length limit for the object type:**
103
+
104
+ | Object type | Name limit | Field/sub-element limit |
105
+ |---|---|---|
106
+ | CLAS, INTF | **30 chars** | method names: **30 chars** |
107
+ | TABL, STRU | **30 chars** | **field names: 16 chars** |
108
+ | DDLS (CDS view entity) | **40 chars** | field alias: **30 chars** |
109
+ | DCLS (CDS access control) | **40 chars** | — (name must match its DDLS view) |
110
+ | FUGR (function group) | **26 chars** | function module name: **30 chars** |
111
+ | MSAG (message class) | **20 chars** | — |
112
+ | PROG, DTEL, DOMA, TTYP | **30 chars** | — |
113
+
114
+ → Full length reference: `abapgit-agent ref --topic naming-limits`
115
+
102
116
  Use the object name from `objects.local.md` (or `objects.md` as fallback) in place of `<name>`:
103
117
 
104
118
  | Object Type | Source File | XML File |
@@ -110,7 +124,7 @@ Use the object name from `objects.local.md` (or `objects.md` as fallback) in pla
110
124
  | CDS Access Control (DCLS) | `<name>.dcls.asdcls` | `<name>.dcls.xml` |
111
125
  | Function Group (FUGR) | `<name>.fugr.abap` + includes | `<name>.fugr.xml` |
112
126
  | Table (TABL) | *(none)* | `<name>.tabl.xml` |
113
- | Structure (STRU) | *(none)* | `<name>.stru.xml` |
127
+ | Structure (STRU) | *(none)* | `<name>.tabl.xml` ⚠️ NOT `.stru.xml` |
114
128
  | Data Element (DTEL) | *(none)* | `<name>.dtel.xml` |
115
129
  | Table Type (TTYP) | *(none)* | `<name>.ttyp.xml` |
116
130
  | Domain (DOMA) | *(none)* | `<name>.doma.xml` |
@@ -143,7 +157,7 @@ Anything else (SAP namespace object, or SAP-delivered package)?
143
157
 
144
158
  Object: <NAME> (<Type>)
145
159
  Package: <PACKAGE>
146
- Files: <folder>/<name>.<ext>.abap
160
+ Files: <folder>/<name>.<ext>.abap ← omit this line for XML-only types (TABL/STRU/DTEL/TTYP/DOMA/MSAG)
147
161
  <folder>/<name>.<ext>.xml
148
162
 
149
163
  Shall I proceed?"
@@ -165,26 +179,27 @@ Anything else (SAP namespace object, or SAP-delivered package)?
165
179
 
166
180
  ---
167
181
 
168
- ### 4. Use Syntax Command Before Commit (for CLAS, INTF, PROG, DDLS)
182
+ ### 4. Use Syntax Command Before Commit (for CLAS, INTF, PROG, DDLS, FUGR)
169
183
 
170
184
  ```
171
185
  ❌ WRONG: Make changes → Commit → Push → Pull → Find errors → Fix → Repeat
172
186
  ✅ CORRECT: Make changes → Run syntax → Fix locally → Commit → Push → Pull → Done
173
187
  ```
174
188
 
175
- **For CLAS, INTF, PROG, DDLS files**: Run `syntax` command BEFORE commit to catch errors early.
189
+ **For CLAS, INTF, PROG, DDLS, FUGR files**: Run `syntax` command BEFORE commit to catch errors early.
176
190
 
177
191
  ```bash
178
192
  # Check syntax of local code (no commit/push needed)
179
193
  # Use the actual filename from your project (name comes from objects.local.md)
180
194
  abapgit-agent syntax --files src/<name>.clas.abap
181
195
  abapgit-agent syntax --files src/<name>.ddls.asddls
196
+ abapgit-agent syntax --files src/<name>.fugr.<fm_name>.abap
182
197
 
183
198
  # Check multiple INDEPENDENT files
184
199
  abapgit-agent syntax --files src/<name1>.clas.abap,src/<name2>.clas.abap
185
200
  ```
186
201
 
187
- **For other types (FUGR, TABL, etc.)**: Skip syntax, proceed to commit/push/pull.
202
+ **For other types (TABL, STRU, DCLS, etc.)**: Skip syntax, proceed to commit/push/pull.
188
203
 
189
204
  **Why use syntax command?**
190
205
  - Catches syntax errors BEFORE polluting git history with fix commits
@@ -410,7 +425,39 @@ After activating a class, stop and tell the user: `"Class is activated. Run with
410
425
 
411
426
  ---
412
427
 
413
- ### 10. Probe and PoC Objects Always Z/Y, Never in SAP Packages
428
+ ### 10. Never Run `drop` Command Without Explicit Permission
429
+
430
+ **Never call `abapgit-agent drop` unless the user explicitly confirms.** Dropping an object physically deletes it from the ABAP system — this is irreversible without a subsequent pull.
431
+
432
+ **When to SUGGEST `drop --pull`:**
433
+
434
+ When an object is in a broken or inconsistent state that cannot be resolved by re-pulling:
435
+ - `inspect` reports **"INCLUDE report ... not found"** (stale include in ABAP not present in git)
436
+ - Pull repeatedly fails with **"Activation cancelled"** and re-pulling doesn't fix it
437
+ - Object has a corrupt inactive version that permanently blocks activation
438
+
439
+ In these cases, suggest the fix and wait for confirmation:
440
+
441
+ ```
442
+ "The object ZCL_FOO has an inconsistent state (stale include in ABAP).
443
+ This can be fixed by dropping and re-pulling it:
444
+
445
+ abapgit-agent drop --files abap/zcl_foo.clas.abap --pull
446
+
447
+ This will delete ZCL_FOO from ABAP and immediately re-activate it from git.
448
+ Confirm when ready."
449
+ ```
450
+
451
+ **What `drop --pull` does:**
452
+ 1. Physically deletes the object from the ABAP system
453
+ 2. Immediately re-pulls and re-activates it from git (clean state)
454
+ 3. Does NOT touch the git repository file
455
+
456
+ **Constraint:** Only CLAS, INTF, PROG, TABL, TTYP are supported. DTEL (data elements) are rejected — edit the XML and use `pull` instead.
457
+
458
+ ---
459
+
460
+ ### 11. Probe and PoC Objects — Always Z/Y, Never in SAP Packages
414
461
 
415
462
  ```
416
463
  ❌ WRONG: Create a probe/PoC object with the project's SAP namespace prefix
@@ -436,7 +483,7 @@ Never assume — wait for the user's answer before proceeding.
436
483
 
437
484
  ---
438
485
 
439
- ### 11. Troubleshooting ABAP Issues
486
+ ### 12. Troubleshooting ABAP Issues
440
487
 
441
488
  | Symptom | Tool | When |
442
489
  |---|---|---|
@@ -708,15 +755,18 @@ abapgit-agent pull --files src/<name>.clas.abap --sync-xml
708
755
 
709
756
  ```
710
757
  Modified ABAP files?
711
- ├─ CLAS/INTF/PROG/DDLS files?
758
+ ├─ CLAS/INTF/PROG/DDLS/FUGR files?
712
759
  │ ├─ Independent files (no cross-dependencies)?
713
760
  │ │ └─ ✅ Use: syntax → [abaplint] → commit → push → pull --sync-xml
714
761
  │ └─ Dependent files (interface + class, class uses class)?
715
762
  │ └─ ✅ Use: skip syntax → [abaplint] → commit → push → pull --sync-xml
716
- └─ Other types (FUGR, TABL, STRU, DTEL, TTYP, etc.)?
763
+ └─ Other types (TABL, STRU, DTEL, TTYP, etc.)?
717
764
  ├─ XML-only objects (TABL, STRU, DTEL, TTYP, DOMA, MSAG)?
718
765
  │ └─ ✅ Use: skip syntax → [abaplint] → commit → push → pull --files abap/ztable.tabl.xml --sync-xml
719
- └─ FUGR and other complex objects?
766
+ ├─ DCLS (CDS access control)?
767
+ │ └─ ✅ Use: skip syntax → [abaplint] → commit → push → pull --files abap/zc_view.dcls.xml --sync-xml
768
+ │ ⚠️ Pass the .xml file — pull --files does NOT accept .asdcls extensions
769
+ └─ Other complex objects?
720
770
  └─ ✅ Use: skip syntax → [abaplint] → commit → push → pull --sync-xml → (if errors: inspect)
721
771
 
722
772
  [abaplint] = run abapgit-agent lint only if .abaplint.json exists in repo root
@@ -736,6 +786,7 @@ Modified ABAP files?
736
786
  | `ref --topic exceptions` | Exception Handling |
737
787
  | `ref --topic classes` | ABAP Classes and Objects |
738
788
  | `ref --topic objects` | Object Naming Conventions (defaults) |
789
+ | `ref --topic naming-limits` | Naming Length Limits — 30/16/40 char rules per type (CRITICAL before naming anything) |
739
790
  | `ref --topic comments` | Documentation Comments (ABAP DOC, shorttext, @parameter, CDS `//`, program `*&---`) |
740
791
  | `ref --topic testing` | Unit Testing |
741
792
  | `ref --topic unit-testable-code` | Unit Testable Code (Dependency Injection) |
@@ -743,6 +794,7 @@ Modified ABAP files?
743
794
  | `ref --topic cds-testing` | CDS Testing (Test Double Framework) |
744
795
  | `ref --topic json` | JSON Handling |
745
796
  | `ref --topic common-errors` | Common ABAP Errors - Quick Fixes |
797
+ | `ref --topic string-template` | String Templates — syntax, escaping `\{` `\}`, JSON payloads |
746
798
  | `ref --topic abapgit` | abapGit XML Metadata — **use for CDS/DDLS XML**, also CLAS, INTF, PROG, DCLS, FUGR |
747
799
  | `ref --topic abapgit-xml-only` | abapGit XML Metadata — XML-only objects (TABL, STRU, DTEL, TTYP, DOMA, MSAG) |
748
800
  | `ref --topic abapgit-fugr` | abapGit XML Metadata — Function Group (FUGR) details |
@@ -22,10 +22,13 @@ A FUGR with group name `ZMY_FUGR` and one FM `ZMY_MY_FUNCTION` requires these fi
22
22
  | `zmy_fugr.fugr.xml` | Main XML: group description, includes list, FM interfaces |
23
23
  | `zmy_fugr.fugr.lzmy_fugrtop.abap` | TOP include source |
24
24
  | `zmy_fugr.fugr.lzmy_fugrtop.xml` | TOP include metadata (`SUBC=I`) |
25
- | `zmy_fugr.fugr.saplzmy_fugr.abap` | Main include source |
25
+ | `zmy_fugr.fugr.saplzmy_fugr.abap` | Main include source (lists all U-includes) |
26
26
  | `zmy_fugr.fugr.saplzmy_fugr.xml` | Main include metadata (`SUBC=F`) |
27
+ | `zmy_fugr.fugr.lzmy_fugru01.abap` | FM implementation include (one per FM: U01, U02, …) |
27
28
  | `zmy_fugr.fugr.zmy_my_function.abap` | FM source (one file per FM, named after FM in lowercase) |
28
29
 
30
+ > **7 files total for one FM** (6 without the U01 include causes a pull error — the SAPL source references `LZMY_FUGRU01` which abapGit can't find). For a second FM, add `lzmy_fugru02.abap` and `zmy_second_function.abap`.
31
+
29
32
  ---
30
33
 
31
34
  ### `zmy_fugr.fugr.xml`
@@ -145,15 +148,28 @@ FUNCTION zmy_my_function.
145
148
  ENDFUNCTION.
146
149
  ```
147
150
 
151
+ ### `zmy_fugr.fugr.lzmy_fugru01.abap`
152
+
153
+ The FM implementation include — **always required**. The SAPL source references `INCLUDE LZMY_FUGRU01.` so this file must exist or the pull fails.
154
+
155
+ ```abap
156
+ *----------------------------------------------------------------------*
157
+ ***INCLUDE LZMY_FUGRU01.
158
+ *----------------------------------------------------------------------*
159
+ ```
160
+
161
+ For a second FM, create `zmy_fugr.fugr.lzmy_fugru02.abap` with the same pattern (replacing `U01` with `U02`).
162
+
148
163
  ---
149
164
 
150
165
  ## Key Rules
151
166
 
152
- - **Include naming**: TOP = `L<GROUP>TOP`, main = `SAPL<GROUP>` — uppercase in XML and filenames
167
+ - **Include naming**: TOP = `L<GROUP>TOP`, main = `SAPL<GROUP>`, FM implementation = `L<GROUP>U01` (U02, U03, …) — uppercase in XML and filenames
153
168
  - **FM source file**: named after the FM in **lowercase** (`zmy_my_function.abap`, not `ZMY_MY_FUNCTION.abap`)
169
+ - **U-include file required**: `lzmy_fugru01.abap` must exist — the SAPL source references it; missing it causes a pull error
154
170
  - **`INCLUDES` list** in the main XML: only lists TOP and SAPL includes — FM source includes are implicit
155
171
  - **`REMOTE_CALL>R`**: add only for RFC-enabled FMs; omit for local FMs
156
172
  - **Optional parameters**: include both `<OPTIONAL>X</OPTIONAL>` and `<DEFAULT>...</DEFAULT>`
157
- - **`DOCUMENTATION` section**: omit entirely if no parameter descriptions neededmissing docs cause no diff
173
+ - **`DOCUMENTATION` section**: the serializer always writes `<DOCUMENTATION>` with one `<RSFDO>` entry per parameter (containing only `<PARAMETER>` and `<KIND>P</KIND>`, no `<STEXT>`). Always include it omitting it causes a permanent "M" diff
158
174
  - **Screens/CUA**: omit `DYNPROS`/`CUA` sections for screenless function groups
159
175
  - **Multiple FMs**: add one `<item>` per FM in `FUNCTIONS`; add one `INCLUDE` line per FM in the SAPL source
@@ -170,6 +170,12 @@ A **text table** stores translatable texts for another table (the "main table").
170
170
 
171
171
  > Pull with: `pull --files src/zmy_dtel.dtel.xml`
172
172
 
173
+ **Two variants — choose based on whether the DTEL defines its own type or references a domain:**
174
+
175
+ #### Variant 1: Built-in type (no domain)
176
+
177
+ Use when the data element directly defines `DATATYPE` and `LENG` without referencing a domain.
178
+
173
179
  ```xml
174
180
  <?xml version="1.0" encoding="utf-8"?>
175
181
  <abapGit version="v1.0.0" serializer="LCL_OBJECT_DTEL" serializer_version="v1.0.0">
@@ -192,13 +198,38 @@ A **text table** stores translatable texts for another table (the "main table").
192
198
  </abapGit>
193
199
  ```
194
200
 
201
+ #### Variant 2: Domain reference
202
+
203
+ Use when the data element's type and length come from an existing domain (`DOMNAME`). Do **not** include `DATATYPE` or `LENG` — the domain owns those.
204
+
205
+ ```xml
206
+ <?xml version="1.0" encoding="utf-8"?>
207
+ <abapGit version="v1.0.0" serializer="LCL_OBJECT_DTEL" serializer_version="v1.0.0">
208
+ <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
209
+ <asx:values>
210
+ <DD04V>
211
+ <ROLLNAME>ZMY_DTEL</ROLLNAME>
212
+ <DDLANGUAGE>E</DDLANGUAGE>
213
+ <DDTEXT>Description of data element</DDTEXT>
214
+ <REPTEXT>Description</REPTEXT>
215
+ <SCRTEXT_S>Short text</SCRTEXT_S>
216
+ <SCRTEXT_M>Medium text</SCRTEXT_M>
217
+ <SCRTEXT_L>Long description text</SCRTEXT_L>
218
+ <DTELMASTER>E</DTELMASTER>
219
+ <DOMNAME>ZMY_DOMAIN</DOMNAME>
220
+ </DD04V>
221
+ </asx:values>
222
+ </asx:abap>
223
+ </abapGit>
224
+ ```
225
+
195
226
  **Key Fields**:
196
227
  - `ROLLNAME`: Data element name
197
228
  - `DDTEXT`: Description (**not** `DESCRIPT`)
198
229
  - `REPTEXT` / `SCRTEXT_S` / `SCRTEXT_M` / `SCRTEXT_L`: Field labels (report heading, short, medium, long)
199
230
  - `DTELMASTER`: Language key for label master (`E` for English)
200
- - `DATATYPE`: Data type (`CHAR`, `NUMC`, `DATS`, `TIMS`, `INT4`, etc.)
201
- - `LENG`: Length padded to 6 digits (e.g. `000010` for 10 characters)
231
+ - `DATATYPE` + `LENG`: Use for built-in type variant only (e.g. `CHAR` + `000010`)
232
+ - `DOMNAME`: Use for domain-reference variant only omit `DATATYPE` and `LENG` entirely
202
233
 
203
234
  **Omit `<PARAMID>`** unless you specifically need a SET/GET parameter ID — the serializer omits it when empty.
204
235
 
@@ -206,10 +237,14 @@ A **text table** stores translatable texts for another table (the "main table").
206
237
 
207
238
  ### Structure (STRU)
208
239
 
209
- **Filename**: `src/zmy_struct.stru.xml`
240
+ **Filename**: `src/zmy_struct.tabl.xml`
210
241
 
211
- > abapGit uses the same TABL serializer for STRU.
212
- > Pull with: `pull --files src/zmy_struct.stru.xml`
242
+ > ⚠️ **Use `.tabl.xml` extension, NOT `.stru.xml`** abapGit serializes structures with the TABL
243
+ > serializer and registers them as object type `TABL`. A `.stru.xml` filename causes
244
+ > "Step DDIC is only for DDIC objects" because abapGit treats it as object type `STRU`,
245
+ > which is not in its DDIC activation list.
246
+ >
247
+ > Pull with: `pull --files src/zmy_struct.tabl.xml`
213
248
 
214
249
  ```xml
215
250
  <?xml version="1.0" encoding="utf-8"?>
@@ -221,16 +256,37 @@ A **text table** stores translatable texts for another table (the "main table").
221
256
  <DDLANGUAGE>E</DDLANGUAGE>
222
257
  <TABCLASS>INTTAB</TABCLASS>
223
258
  <DDTEXT>Description of the structure</DDTEXT>
224
- <CONTFLAG>A</CONTFLAG>
259
+ <EXCLASS>1</EXCLASS>
225
260
  </DD02V>
261
+ <DD03P_TABLE>
262
+ <DD03P>
263
+ <FIELDNAME>FIELD1</FIELDNAME>
264
+ <ROLLNAME>S_CARR_ID</ROLLNAME>
265
+ <ADMINFIELD>0</ADMINFIELD>
266
+ <SHLPORIGIN>D</SHLPORIGIN>
267
+ <COMPTYPE>E</COMPTYPE>
268
+ </DD03P>
269
+ <DD03P>
270
+ <FIELDNAME>FIELD2</FIELDNAME>
271
+ <ROLLNAME>S_CARRNAME</ROLLNAME>
272
+ <ADMINFIELD>0</ADMINFIELD>
273
+ <COMPTYPE>E</COMPTYPE>
274
+ </DD03P>
275
+ </DD03P_TABLE>
226
276
  </asx:values>
227
277
  </asx:abap>
228
278
  </abapGit>
229
279
  ```
230
280
 
231
- **Key difference from TABL**: `TABCLASS` is `INTTAB` (internal table / structure) instead of `TRANSP`.
281
+ **Key differences from TABL**:
282
+ - `TABCLASS` is `INTTAB` instead of `TRANSP`
283
+ - No `<CONTFLAG>` — omit it (not written by serializer for structures)
284
+ - `<EXCLASS>1</EXCLASS>` — include it
285
+ - Include `<DD03P_TABLE>` with field definitions from the start (unlike TABL where it is optional on creation)
232
286
 
233
- **Note**: Like TABL, after the first pull abapGit expands the XML with `<DD03P_TABLE>` field definitions.
287
+ **`DD03P` field rules** (same as TABL):
288
+ - Fields with `ROLLNAME` (data element): include `ROLLNAME`, `ADMINFIELD>0`, `SHLPORIGIN` (when domain provides value help — `D` for domain fixed values), `COMPTYPE>E`
289
+ - Fields with raw type (no data element): include `ADMINFIELD>0`, `INTTYPE`, `INTLEN`, `DATATYPE`, `MASK` (before any text fields)
234
290
 
235
291
  ---
236
292
 
@@ -248,13 +304,13 @@ A **text table** stores translatable texts for another table (the "main table").
248
304
  <DD40V>
249
305
  <TYPENAME>ZMY_TTYP</TYPENAME>
250
306
  <DDLANGUAGE>E</DDLANGUAGE>
251
- <DDTEXT>Description of table type</DDTEXT>
252
307
  <ROWTYPE>ZMY_STRUCT</ROWTYPE>
253
308
  <ROWKIND>S</ROWKIND>
254
- <DATATYPE>TABLE_T</DATATYPE>
309
+ <DATATYPE>STRU</DATATYPE>
255
310
  <ACCESSMODE>T</ACCESSMODE>
256
311
  <KEYDEF>D</KEYDEF>
257
312
  <KEYKIND>N</KEYKIND>
313
+ <DDTEXT>Description of table type</DDTEXT>
258
314
  </DD40V>
259
315
  </asx:values>
260
316
  </asx:abap>
@@ -265,7 +321,7 @@ A **text table** stores translatable texts for another table (the "main table").
265
321
  - `TYPENAME`: Table type name
266
322
  - `ROWTYPE`: Row type (a structure or data element name)
267
323
  - `ROWKIND`: Row kind — `S`=Structure/Type, `D`=Data element, `R`=Reference
268
- - `DATATYPE`: Always `TABLE_T` for table types
324
+ - `DATATYPE`: `STRU` when row type is a structure (`ROWKIND=S`); `TABLE_T` only for elementary-type row types
269
325
  - `ACCESSMODE`: Table kind — `T`=Standard, `S`=Sorted, `H`=Hashed
270
326
  - `KEYDEF`: Key definition — `D`=Default (standard key), `K`=User-defined
271
327
  - `KEYKIND`: Key uniqueness — `N`=Non-unique, `U`=Unique
@@ -372,7 +428,7 @@ abapGit uses the view `DD01V` as the root element (not `DD01L`). The serializer
372
428
  <SPRSL>E</SPRSL>
373
429
  <ARBGB>ZMY_MSGS</ARBGB>
374
430
  <MSGNR>000</MSGNR>
375
- <TEXT>Object &1 not found</TEXT>
431
+ <TEXT>Object &amp;1 not found</TEXT>
376
432
  </T100>
377
433
  <T100>
378
434
  <SPRSL>E</SPRSL>
@@ -265,7 +265,7 @@ abapGit's serializer **omits fields that have their default value**. Writing ext
265
265
  - `SOURCE_TYPE W` → View Entity (`define view entity`, modern — **use by default**)
266
266
  - `SOURCE_TYPE V` → View (`define view` + `@AbapCatalog.sqlViewName`, legacy)
267
267
 
268
- → For DDL source syntax: `abapgit-agent ref --topic cds-abapgit`
268
+ → For DDL source syntax: `abapgit-agent ref --topic cds`
269
269
 
270
270
  ---
271
271
 
@@ -290,6 +290,7 @@ abapGit's serializer **omits fields that have their default value**. Writing ext
290
290
 
291
291
  - `DCLNAME` matches the CDS view name
292
292
  - Source file contains the DCL (`@MappingRole ... define role ...`)
293
+ - **Pull with the `.xml` file, not `.asdcls`**: `pull --files src/zc_my_view.dcls.xml` — the `pull --files` filter does not accept `.asdcls` extensions
293
294
 
294
295
  ---
295
296
 
@@ -80,6 +80,41 @@ lv_response = lv_response && '"key":"val"}'.
80
80
  | `DATA(lv) = 'literal'.` followed by `&&` | ❌ | Infers `C LENGTH N`, truncates |
81
81
  | `DATA(lv) = 'literal'.` used only in `\|{ lv }\|` | ⚠️ | Technically works but misleading — prefer explicit type |
82
82
  | `DATA(lv) = 'X'.` used as abap_bool flag | ✅ | `C LENGTH 1` is correct for flags |
83
+ | `DATA(lv) = COND string( WHEN ... THEN str+off ELSE str ).` | ❌ | Offset notation on `string` inside COND raises `CX_SY_RANGE_OUT_OF_BOUNDS` at runtime |
84
+
85
+ ### The offset-notation-in-COND trap
86
+
87
+ Offset/length notation (`str+off` or `str(len)`) on a `string`-typed variable **cannot appear
88
+ as a result expression inside `COND`** — even when the `COND` is explicitly typed as `string`.
89
+ ABAP evaluates both branch types at generation time and the offset expression on a dynamic
90
+ string is invalid, causing a `CX_SY_RANGE_OUT_OF_BOUNDS` crash at runtime.
91
+
92
+ ```abap
93
+ DATA lv_file TYPE string VALUE 'src/foo.clas.abap'.
94
+ DATA(lv_pos) = find( val = lv_file sub = '/' occ = -1 ).
95
+
96
+ * WRONG — CX_SY_RANGE_OUT_OF_BOUNDS at runtime
97
+ DATA(lv_path) = COND string(
98
+ WHEN lv_pos > 0 THEN '/' && lv_file(lv_pos + 1) " ← offset on string = crash
99
+ ELSE '/' ).
100
+
101
+ * CORRECT — use substring() which returns string and is safe in COND
102
+ DATA(lv_path) = COND string(
103
+ WHEN lv_pos > 0 THEN '/' && substring( val = lv_file len = lv_pos + 1 )
104
+ ELSE '/' ).
105
+
106
+ * ALSO CORRECT — keep IF/ELSE with DATA x TYPE string
107
+ DATA lv_path TYPE string.
108
+ IF lv_pos > 0.
109
+ DATA(lv_len) = lv_pos + 1.
110
+ lv_path = '/' && lv_file(lv_len).
111
+ ELSE.
112
+ lv_path = '/'.
113
+ ENDIF.
114
+ ```
115
+
116
+ **Rule**: whenever the prefer_inline quickfix would produce `COND ... THEN str+off` or
117
+ `COND ... THEN str(len)`, use `substring()` instead, or keep the `IF/ELSE` form.
83
118
 
84
119
  ### Rule of thumb
85
120
 
@@ -8,7 +8,7 @@ grand_parent: ABAP Development
8
8
 
9
9
  # Common ABAP Errors - Quick Fixes
10
10
 
11
- **Searchable keywords**: error, syntax error, field mismatch, fixed point, comma, host variable, @ prefix, type incompatible
11
+ **Searchable keywords**: error, syntax error, field mismatch, fixed point, comma, host variable, @ prefix, type incompatible, string template, expression limiter, literal brace, http 500, xml metadata mismatch, interface description, descript, recompilation, offset notation, cond trap, cx_sy_range_out_of_bounds
12
12
 
13
13
  ## Fixed Point Arithmetic Error
14
14
 
@@ -119,6 +119,83 @@ or declare the variable explicitly with `TYPE string`.
119
119
 
120
120
  ---
121
121
 
122
+ ## Offset Notation on String in COND — CX_SY_RANGE_OUT_OF_BOUNDS
123
+
124
+ **Symptom**: Pull succeeds but ABAP crashes at runtime with `CX_SY_RANGE_OUT_OF_BOUNDS`
125
+ inside a method using `COND`.
126
+
127
+ **Root cause**: Offset/length notation on a `string` variable (`str+off`, `str(len)`)
128
+ **cannot be used as a result expression inside `COND`** — even with an explicit `COND string(...)` type.
129
+ The abaplint `prefer_inline` quickfix can introduce this automatically when converting
130
+ an `IF/ELSE` block that assigns from a string-variable offset.
131
+
132
+ ```abap
133
+ * WRONG — crashes at runtime with CX_SY_RANGE_OUT_OF_BOUNDS
134
+ DATA(lv_path) = COND string(
135
+ WHEN lv_pos > 0 THEN '/' && lv_file(lv_pos + 1) " ← string offset in COND
136
+ ELSE '/' ).
137
+
138
+ * CORRECT — use substring() instead
139
+ DATA(lv_path) = COND string(
140
+ WHEN lv_pos > 0 THEN '/' && substring( val = lv_file len = lv_pos + 1 )
141
+ ELSE '/' ).
142
+ ```
143
+
144
+ **Fix**: Replace `str+off` / `str(len)` inside `COND` results with `substring( val = str off = off )` or
145
+ `substring( val = str len = len )`, or revert to the `IF/ELSE` form with `DATA x TYPE string`.
146
+
147
+ → See `abaplint.md` for the full safe/unsafe table for `prefer_inline`.
148
+
149
+ ---
150
+
151
+ ## XML Metadata Mismatch — HTTP 500 on Pull
152
+
153
+ **Symptom**: `pull` returns HTTP 500 with no short dump (ST22) for the request user.
154
+ Other objects pull fine; only a specific interface or class fails.
155
+
156
+ **Root cause**: The `.intf.xml` or `.clas.xml` file in git has a metadata field (e.g. `DESCRIPT`,
157
+ `UNICODE`, `STATE`) that differs from the active ABAP system value. abapGit writes the git
158
+ value back to VSEOINTERF/VSEOCLASS, which forces the SAP class framework to recompile all
159
+ implementing/inheriting objects. If any implementing class has a syntax or generation
160
+ issue with the current active source, the recompilation crashes outside the normal exception
161
+ handler — producing HTTP 500 with no dump.
162
+
163
+ **Diagnosis**:
164
+ 1. No dump in ST22 for your user → not a user-code crash
165
+ 2. Only one specific INTF/CLAS fails → metadata delta in its XML triggers recompilation
166
+ 3. Check what differs: `abapgit-agent view --objects ZIF_MY_INTF --type INTF` and compare
167
+ `DESCRIPT` / other fields with the XML file in git
168
+
169
+ **Fix**: Sync the XML to match the ABAP system value. The easiest way:
170
+
171
+ ```bash
172
+ # Pull without --sync-xml first to let abapGit rewrite the XML from the system
173
+ abapgit-agent pull --files abap/zif_my_intf.intf.abap --sync-xml
174
+ ```
175
+
176
+ Or manually correct the field in the XML file to match the system value, then push and pull.
177
+
178
+ **Prevention**: Always use `--sync-xml` after pulling new objects so the XML stays in sync
179
+ with what the ABAP serializer produces.
180
+
181
+ ---
182
+
183
+ **Error**: `Expression limiter '{' in string template not followed by space`
184
+
185
+ Literal `{` and `}` (e.g. in JSON payloads) must be escaped as `\{` and `\}` inside `|...|`.
186
+
187
+ ```abap
188
+ " WRONG — unescaped { in JSON triggers parse error
189
+ rv_result = |{"success":"X","name":"{ lv_name }"}|.
190
+
191
+ " CORRECT
192
+ rv_result = |\{"success":"X","name":"{ lv_name }"\}|.
193
+ ```
194
+
195
+ → Full escaping rules and examples: `abapgit-agent ref --topic string-template`
196
+
197
+ ---
198
+
122
199
  ## See Also
123
200
  - **ABAP SQL** (sql.md) - for SQL syntax rules
124
201
  - **CDS Views** (cds.md) - for CDS selection patterns
@@ -20,6 +20,7 @@ This folder contains detailed ABAP coding guidelines that can be searched using
20
20
  | `cds.md` | CDS Views |
21
21
  | `classes.md` | ABAP Classes and Objects |
22
22
  | `objects.md` | Object Naming Conventions |
23
+ | `naming-limits.md` | Naming Length Limits (30/16/40 char rules per type) |
23
24
  | `json.md` | JSON Handling |
24
25
  | `abapgit.md` | abapGit XML Metadata Templates |
25
26
  | `unit-testable-code.md` | Unit Testable Code Guidelines (Dependency Injection) |