-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathabaplint.jsonc
More file actions
556 lines (556 loc) · 21.8 KB
/
Copy pathabaplint.jsonc
File metadata and controls
556 lines (556 loc) · 21.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
{
"global": {
"files": "/src/**/*.*",
// z2ui5_cl_smps_evt_tck is a RAP business event handler. Its two
// constructs - CLASS ... DEFINITION PUBLIC FOR EVENTS OF <entity> in the
// global class and METHODS ... FOR ENTITY EVENT <evt> FOR <entity>~<evt>
// in the handler pool - have no grammar in abaplint, so the class pool
// does not parse. Every finding on the two ABAP files is a consequence
// of that parse failure, not of the ABAP. The structure error comes from
// the parser itself rather than from a rule, so a per rule "exclude"
// cannot reach it and the whole file has to be silenced. Scoped to the
// ABAP: the class .clas.xml is not listed, so object_naming and
// xml_consistency still cover the object. Drop this once abaplint parses
// the RAP event syntax.
"noIssues": [
"z2ui5_cl_smps_evt_tck\\.clas\\.abap$",
"z2ui5_cl_smps_evt_tck\\.clas\\.locals_imp\\.abap$"
]
},
"dependencies": [
{
"url": "https://github.com/abapedia/steampunk-2305-api",
"folder": "/deps",
"files": "/src/**/*.*"
},
{
"url": "https://github.com/abap2UI5/abap2UI5",
"branch": "main",
"folder": "/abap2UI5",
"files": "/src/**/*.*"
}
],
"syntax": {
// EML (READ/MODIFY/COMMIT ENTITIES) requires ABAP Platform >= 1909,
// therefore this sample is not downported like the other repositories
"version": "v757",
// the RAP business object /DMO/I_TRAVEL_M of the SAP flight reference
// scenario is not part of the dependencies, only Z2UI5* objects are
// resolved strictly
"errorNamespace": "^Z2UI5"
},
// ===================================================================
// THE RULE BLOCK BELOW IS THE SHARED APP RULE SET, and its SOURCE is
// abap2UI5/abap2UI5 `.github/abaplint/app-rules.json` - where the rest of
// "how to write an abap2UI5 app" lives (the build-an-app and
// view-chain-layout skills, docs/agents/building-apps.md, abap-check,
// ui5-check). Change it THERE first, then copy it here; the three sample
// repositories are consumers of it, not peers of each other.
//
// `npm run check:app-rules` compares this block against the source, as
// PARSED SETTINGS. The peer checker it replaced compared rule NAMES, so
// switching a rule to false read as no change at all - which is precisely
// the drift it existed to catch.
//
// The ONE exception is "object_naming", the last rule in the file: it
// encodes which repository you are in (SMP / SMPC / SMPS) and is the only
// thing above the line that may differ. Everything else - what is checked,
// what is not, and why - is a joint decision of the three corpora.
//
// Every rule abaplint ships is listed: all 188. 171 are on, 17 are off and
// each says why. A rule is NEVER left out of the file. When an abaplint
// upgrade adds one, add the key: on if all three corpora pass, off with the
// reason if they do not. An unlisted rule reads as "nobody decided" rather
// than "decided against", and that is exactly how samples ran 17 rules for
// two years without anyone noticing.
//
// WRITE A CONFIGURED RULE'S FLAGS OUT IN FULL. abaplint replaces the whole
// options object, so a partial one silently turns every flag it omits OFF -
// "check_subrc": { "selectTable": false } disables the rule entirely
// instead of narrowing it.
// ===================================================================
"rules": {
// --- off: AGENTS.md documents the opposite convention -------------
// Type prefixes are for tables ("t_") and structures ("s_") only, local
// types carry "ty_s_" / "ty_t_", and scalars and object references carry
// no prefix at all. These four rules want Hungarian notation instead
// ("^L._.+$", "^M._.+$", "^I._.+$") or want the prefixes gone altogether.
"local_variable_names": false,
"class_attribute_names": false,
"method_parameter_names": false,
"no_prefixes": false,
// An abap2UI5 app binds its own public attributes into the view -
// client->_bind( quantity ) reads the attribute the view writes back to.
// The public attribute IS the model, not an encapsulation leak.
"no_public_attributes": false,
// Demo apps, read for their view code, not a published API. The
// explanation lives in the overview catalog and in the MessageStrip the
// app renders. abap2UI5 keeps this off for the same reason.
"abapdoc": false,
// --- off: the view builder chain owns its own layout --------------
// A view is one statement spanning up to several hundred lines, laid out
// by rules that the linter's chain-house-layout ("npm run check:abap2ui5") gates -
// and that gate is stricter than anything here. Every one of these rules
// reads a chain as a malformed parameter list: 5,087 findings from
// line_break_multiple_parameters alone, all of them correct chains.
"line_break_multiple_parameters": false,
"keep_single_parameter_on_one_line": false,
"align_parameters": false,
"in_statement_indentation": false,
"indentation": false,
// Blank lines inside a chain separate the view's sections - the Shell
// from the Page, the header from the form. Blank lines inside one
// statement is exactly what this rule forbids.
"empty_line_in_statement": false,
// A chain and a VALUE #( ) data table both close with ")." on its own
// line - 70 of them in samples-controls, in 61 files. Same layout
// question as the five rules above, same answer.
"line_only_punc": false,
// --- off: the samples declare deliberately ------------------------
// Both rules push declarations into the branch that first uses them. A
// sample is read top-down, so its data is declared where the reader
// looks for it, and the shared context classes carry downported shapes
// (DATA temp9, DATA comps LIKE temp9) that cannot be inlined at all.
"prefer_inline": false,
"no_inline_in_optional_branches": false,
// --- off: the proposed rewrite does not activate ------------------
// The MOVE-CORRESPONDING statements left in the tree copy between two
// generic "TYPE any" field symbols. CORRESPONDING #( ) derives its type
// from the target, and a generic field symbol has none at compile time,
// so the rewrite parses but does not activate on a real system.
"prefer_corresponding": false,
// The two .mp3 files in samples-stack (08/01) are SMIM objects whose
// parent MIME folder lives on the system, not in the repository, so the
// rule cannot resolve it from the sources alone.
"smim_consistency": false,
// --- on, with settings --------------------------------------------
// Hard ABAP limit, not a convention: a longer line breaks the abapGit
// import with "Literals across more than one line are not allowed".
"line_length": {
"length": 255
},
// "ty_" covers the ty_s_ / ty_t_ scheme all three repositories use.
"types_naming": {
"pattern": "^TY_"
},
// The union of what the three corpora legitimately hold. samples and
// samples-controls are classes and packages only; samples-stack adds the
// RAP and on-premise objects. Anything else - a report, a function
// group, a message class - is still refused.
"allowed_object_types": {
"allowed": [
"CLAS",
"DEVC",
"INTF",
"TABL",
"DTEL",
"DDLS",
"BDEF",
"SRVD",
"SRVB",
"SICF",
"SAPC",
"SAMC",
"SUSH",
"SMIM",
"G4BA"
]
},
// Two flags stay off because both read deliberate column alignment as a
// double space and would strip it: "keywords" aligns keyword operands
// (EXPORTING p_name over RECEIVING p_descr_ref), "endParen" aligns the
// rows of a literal data table before their closing paren (676 of those
// in samples-controls). The two that are left catch real sloppiness.
"double_space": {
"keywords": false,
"startParen": true,
"endParen": false,
"afterColon": true
},
// Two blank lines separate methods, so three is already one too many.
"sequential_blank": {
"lines": 3
},
// Restricted to literal constants on the left, which is the half worth
// having ("IF 5 = x"). Unrestricted, the rule also demands
// "lines( t ) < i" instead of "i > lines( t )" - 13 of those across the
// three corpora, and flipping them reads worse than the code it replaces.
"no_yoda_conditions": {
"onlyConstants": true
},
// All eight detectors on. endselect / execSQL / kernelCall /
// communication / systemCall are not keys of this rule any more - they
// moved to dangerous_statement below, which carries them.
"avoid_use": {
"skipQuickFix": false,
"define": true,
"statics": true,
"defaultKey": true,
"break": true,
"testSeams": true,
"describeLines": true,
"exportToMemory": true,
"exportToDatabase": true
},
// Every flag on except dynamicSQL: "SELECT * FROM (mv_table)" is not an
// accident in this corpus, it is the subject of the generic table
// browser samples in samples/src/00/98.
"dangerous_statement": {
"execSQL": true,
"kernelCall": true,
"systemCall": true,
"insertReport": true,
"generateDynpro": true,
"generateReport": true,
"generateSubroutine": true,
"deleteReport": true,
"deleteTextpool": true,
"insertTextpool": true,
"deleteDynpro": true,
"exportDynpro": true,
"editorCallForReport": true,
"dynamicSQL": false,
"ignoreRAPQueryProvider": true
},
// Every flag on except the two SELECT ones. The rule earns its keep with
// what is left - it found nine unchecked ASSIGN obj->(`NAME`) (reading
// an unassigned field symbol dumps) and four READ TABLE whose work area
// was used unconditionally, one of which inserted a stale row whenever
// the selection was empty.
// selectSingle / selectTable are off because "no rows" is never an error
// here: a table SELECT either feeds a binding, where an empty table is a
// legitimate view, or is read back through VALUE #( lt[ 1 ] OPTIONAL ),
// which handles the empty case in the expression itself.
"check_subrc": {
"openDataset": true,
"authorityCheck": true,
"selectSingle": false,
"selectTable": false,
"updateDatabase": true,
"insertDatabase": true,
"modifyDatabase": true,
"deleteDatabase": true,
"readTable": true,
"assign": true,
"find": true
},
// Every block must have code except WHEN: an event whose only job is to
// force a round-trip is a legitimate empty branch, and the samples that
// have one say so in a comment where the code would be.
"empty_structure": {
"loop": true,
"loopAllowIfSubrc": true,
"if": true,
"while": true,
"case": true,
"select": true,
"do": true,
"at": true,
"try": true,
"when": false
},
// The overview app is hand-written but held to its shape by
// scripts/check-overview.mjs - its render method is one long emit, and
// shortening it means reworking the checked structure, not one method.
"method_length": {
"statements": 100,
"errorWhenEmpty": false,
"ignoreTestClasses": true,
"checkForms": true,
"checkFunctionModules": true,
"exclude": [
"z2ui5_cl_smpc_app_000\\.clas\\."
]
},
// On, because non-7-bit source is an abapGit round-trip hazard - and it
// caught 22 em-dashes and ellipses in comments, which are now ASCII.
// The excluded files are the ones whose DATA is non-ASCII: ports whose
// product descriptions, supplier names or i18n strings come from the
// original demo kit sample, where scripts/data-fidelity.mjs compares
// them against that original. Changing them to ASCII would fail that
// gate. app_185 is the non-breaking-space constant the sample is about.
"7bit_ascii": {
"exclude": [
"z2ui5_cl_smpc_app_(012|040|092|103|104|114|134|185|191|194|215|218|254|290|302|303|350|356|357|358|360|445|525|558|565|572|575|578|579|580|584|611)\\.clas\\.",
"z2ui5_cl_smpc_app_000\\.clas\\."
]
},
// --- on, scoped to what the RAP corpus can comply with -------------
// Excluded for samples-stack: CDS entities, actions and fields are
// CamelCase by definition (Ticket, TravelUuid, Activate) and the rule
// reads every one of them as a lower-case violation - 31 findings, all
// of them correct ABAP.
"keyword_case": {
"style": "upper",
"ignoreExceptions": true,
"ignoreLowerClassImplmentationStatement": true,
"exclude": [
"z2ui5_cl_smps_"
],
"ignoreKeywords": []
},
// A RAP behavior implementation is called by the runtime, never from
// ABAP, so every handler in a bp_ pool reads as unused - and so does a
// variable a RAISE ENTITY EVENT consumes, which abaplint has no grammar
// for.
"unused_methods": {
"exclude": [
"z2ui5_cl_smps_bp_[a-z]+\\.clas\\.locals_imp\\."
]
},
"unused_variables": {
"exclude": [
"z2ui5_cl_smps_bp_[a-z]+\\.clas\\.locals_imp\\."
]
},
// lhc_<entity> is the name RAP mandates for a handler class; ^LCL_ is
// not available there.
"local_class_naming": {
"exclude": [
"z2ui5_cl_smps_bp_[a-z]+\\.clas\\.locals_imp\\."
],
"patternKind": "required",
"local": "^LCL_.+$",
"exception": "^LCX_.+$",
"test": "^LTCL_.+$"
},
// A RAP behavior pool is ABSTRACT FINAL by definition - that is the
// required shape, not a mistake.
"check_abstract": {
"exclude": [
"z2ui5_cl_smps_bp_[a-z]+\\.clas\\."
]
},
// The persistent and draft tables are referenced from the CDS and
// behavior definitions, which abaplint does not trace into.
"unused_ddic": {
"exclude": [
"z2ui5_(t|d)_smps_"
]
},
// Excluded for the two apps that declare TYPE RESPONSE FOR FAILED /
// REPORTED EARLY - fully typed RAP syntax abaplint reads as implicit.
"fully_type_constants": {
"checkData": true,
"exclude": [
"z2ui5_cl_smps_app_(007|010)\\.clas\\."
]
},
// Excluded for the RAP handler pools: their SELECT SINGLE is an
// aggregate (MAX( travel_id )), which returns exactly one row by
// definition - the rule does not model that.
"select_single_full_key": {
"allowPseudo": true,
"exclude": [
"z2ui5_cl_smps_bp_[a-z]+\\.clas\\.locals_imp\\."
]
},
// Excluded for samples-stack app 319: the operator mapping there is a
// table written as a CASE, one WHEN per line, and splitting it costs the
// shape that makes it readable.
"max_one_statement": {
"exclude": [
"z2ui5_cl_smps_app_319\\.clas\\."
]
},
// ABAP Push Channels are on-premise only and therefore absent from the
// steampunk API dependency, so app 489's superclass cannot be resolved
// and every reference to it reports as unknown.
"check_syntax": {
"exclude": [
"z2ui5_cl_smps_app_489(_ws)?\\.clas\\."
]
},
// See check_syntax above - same class, same missing superclass.
"superclass_final": {
"exclude": [
"z2ui5_cl_smps_app_489_ws\\.clas\\."
]
},
// Every category set to the namespace the three repositories share. The
// per-category SAP prefixes (ZI_, ZC_, ZR_, ...) are not the scheme here:
// samples-stack names its root view entities Z2UI5_R_SMPS_<object>.
"cds_naming": {
"basicInterfaceView": "Z2UI5_",
"compositeInterfaceView": "Z2UI5_",
"consumptionView": "Z2UI5_",
"basicRestrictedReuseView": "Z2UI5_",
"compositeRestrictedReuseView": "Z2UI5_",
"privateView": "Z2UI5_",
"remoteAPIView": "Z2UI5_",
"viewExtend": "Z2UI5_",
"extensionIncludeView": "Z2UI5_",
"derivationFunction": "Z2UI5_",
"abstractEntity": "Z2UI5_"
},
// --- on, as shipped -----------------------------------------------
"add_test_attributes": true,
"aff_and_xml": true,
"align_pseudo_comments": true,
"align_type_expressions": true,
"allowed_object_naming": true,
"ambiguous_statement": true,
"begin_end_names": true,
"begin_single_include": true,
"call_transaction_authority_check": true,
"catch_and_raise": true,
"cds_association_name": true,
"cds_comment_style": true,
"cds_field_order": true,
"cds_legacy_view": true,
"cds_parser_error": true,
"chain_mainly_declarations": true,
"change_if_to_case": true,
"check_comments": true,
"check_ddic": true,
"check_include": true,
"check_text_elements": true,
"check_transformation_exists": true,
"classic_exceptions_overlap": true,
"clear_exporting_parameters": true,
"cloud_types": true,
"colon_missing_space": true,
"commented_code": true,
"constant_classes": true,
"constructor_visibility_public": true,
"contains_tab": true,
"cyclic_oo": true,
"cyclomatic_complexity": true,
"db_operation_in_loop": true,
"definitions_top": true,
"description_empty": true,
"downport": true,
"dynpro_checks": true,
"easy_to_find_messages": true,
"empty_event": true,
"empty_statement": true,
"exit_or_check": true,
"expand_macros": true,
"exporting": true,
"fm_global_parameters_obsolete": true,
"forbidden_identifier": true,
"forbidden_pseudo_and_pragma": true,
"forbidden_void_type": true,
"form_tables_obsolete": true,
"fully_type_itabs": true,
"function_module_recommendations": true,
"functional_writing": true,
"global_class": true,
"identical_conditions": true,
"identical_contents": true,
"identical_descriptions": true,
"identical_form_names": true,
"identical_move": true,
"if_in_if": true,
"implement_methods": true,
"implicit_start_of_selection": true,
"index_completely_contained": true,
"inline_data_old_versions": true,
"intf_referencing_clas": true,
"invalid_table_index": true,
"line_break_style": true,
"local_testclass_consistency": true,
"macro_naming": true,
"main_file_contents": true,
"many_parentheses": true,
"max_one_method_parameter_per_line": true,
"message_exists": true,
"method_implemented_twice": true,
"method_overwrites_builtin": true,
"mix_returning": true,
"modify_only_own_db_tables": true,
"msag_consistency": true,
"names_no_dash": true,
"nesting": true,
"newline_between_methods": true,
"no_aliases": true,
"no_chained_assignment": true,
"no_comments_between_methods": true,
"no_exclamation_escape": true,
"no_external_form_calls": true,
"no_macros": true,
"no_mandt_in_database_operations": true,
"nrob_consistency": true,
"obsolete_statement": true,
"omit_parameter_name": true,
"omit_preceding_zeros": true,
"omit_receiving": true,
"parser_702_chaining": true,
"parser_bad_exceptions": true,
"parser_error": true,
"parser_missing_space": true,
"pragma_style": true,
"prefer_is_not": true,
"prefer_pragmas": true,
// Excluded for samples-stack package 06, which ships at 7.40 SP08 (see
// .github/packages.json): RAISE EXCEPTION NEW is 7.52 syntax. The root
// abaplint.jsonc lints the whole tree at v757 and cannot see a per-package
// release floor - the one-package branch build is the gate that can, and
// it is the one that caught this.
"prefer_raise_exception_new": {
"exclude": ["z2ui5_cl_smps_app_485\\.clas\\."]
},
"prefer_returning_to_exporting": true,
"prefer_xsdbool": true,
"preferred_compare_operator": true,
"prefix_is_current_class": true,
"reduce_procedural_code": true,
"reduce_string_templates": true,
"redundant_conversion": true,
"release_idoc": true,
"remove_descriptions": true,
"rfc_error_handling": true,
"select_add_order_by": true,
"select_performance": true,
"selection_screen_naming": true,
"selection_screen_texts_missing": true,
"short_case": true,
"sicf_consistency": true,
"slow_parameter_passing": true,
"space_before_colon": true,
"space_before_dot": true,
"sql_escape_host_variables": true,
"sql_value_conversion": true,
"start_at_tab": true,
"static_call_via_instance": true,
"strict_sql": true,
"superfluous_value": true,
"sy_modification": true,
"sy_read_restriction": true,
"tabl_enhancement_category": true,
"tables_declared_locally": true,
"try_without_catch": true,
"type_form_parameters": true,
"uncaught_exception": true,
"unknown_types": true,
"unnecessary_chaining": true,
"unnecessary_pragma": true,
"unnecessary_return": true,
"unreachable_code": true,
"unsecure_fae": true,
"unused_macros": true,
"unused_types": true,
"use_bool_expression": true,
"use_class_based_exceptions": true,
"use_line_exists": true,
"use_new": true,
"when_others_last": true,
"whitespace_end": true,
"xml_consistency": true,
// ===================================================================
// THE ONE PER-REPOSITORY RULE - everything above this line is identical
// in samples, samples-controls and samples-stack.
// ===================================================================
// Class names are capped at 25 characters by the leading lookahead. ABAP
// allows 30, but build_rename (see abap2UI5) replaces the namespace
// z2ui5 (5 chars) with up to 9, which costs 4 - so 26 is the hard
// ceiling and 25 keeps one character in reserve. A parallel installation
// therefore never needs truncation patterns.
"object_naming": {
"patternKind": "required",
"severity": "Error",
"clas": "^(?=.{1,25}$)Z2UI5_C(L|X)_SMPS_",
"tabl": "^(?=.{1,16}$)Z2UI5_(T|D)_SMPS_"
}
}
}