ABAP Cleaner : Nettoyage automatique du code

Catégorie
DevOps
Publié
Auteur
Johannes

ABAP Cleaner est un outil open source qui nettoie, formate et modernise automatiquement le code ABAP. Il applique plus de 60 regles de nettoyage et aide a appliquer des standards de code uniformes dans toute l’equipe.

Qu’est-ce que ABAP Cleaner ?

ABAP Cleaner analyse le code ABAP et le transforme automatiquement selon des regles configurables. Contrairement au Pretty Printer, ABAP Cleaner va bien au-dela du simple formatage et modernise egalement les constructions du langage.

AspectPretty PrinterABAP Cleaner
FocusIndentation, majuscules/minusculesModernisation complete du code
Regles~5 regles de base60+ regles configurables
Constructions du langageAucun changementModernisation (p.ex. NEW au lieu de CREATE OBJECT)
Lignes videsRegles simplesRegroupement intelligent
CommentairesAucun changementAlignement et formatage
Performance-Suppression des instructions inutiles
ProfilsFixesConfigurables individuellement

Avantages

  • Coherence : Style de code uniforme dans toute l’equipe
  • Productivite : Le nettoyage automatique economise le travail manuel
  • Modernisation : L’ancienne syntaxe est automatiquement mise a jour
  • Lisibilite : Meilleure structuration et formatage
  • Revue de code : Moins de discussions sur les questions de style
  • Onboarding : Les nouveaux membres de l’equipe ecrivent immediatement du code conforme

Installation dans ADT

Prerequis

  • Eclipse avec ADT (ABAP Development Tools)
  • Eclipse version 2022-03 ou plus recente
  • Java 11 ou plus recent

Installation via Eclipse Marketplace

  1. Ouvrir Eclipse et naviguer vers Help - Eclipse Marketplace
  2. Rechercher “ABAP Cleaner”
  3. Cliquer sur Install et suivre les instructions
  4. Redemarrer Eclipse

Installation manuelle via Update Site

Si le Marketplace n’est pas disponible :

Help → Install New Software...
URL Update Site :
https://sap.github.io/abap-cleaner/updatesite
Fonctionnalites disponibles :
☑ ABAP Cleaner
→ Next → Accept License → Finish → Restart Eclipse

Verifier l’installation

Apres le redemarrage, ABAP Cleaner devrait etre disponible :

┌──────────────────────────────────────────────────────────────┐
│ Barre d'outils ADT │
├──────────────────────────────────────────────────────────────┤
│ │
│ [📁] [💾] [↩️] [↪️] ... [🧹 ABAP Cleaner] │
│ │
│ Ou : Source → Clean Up With Interactive ABAP Cleaner... │
│ Raccourci : Ctrl+4 (configurable) │
│ │
└──────────────────────────────────────────────────────────────┘

Regles de nettoyage principales

ABAP Cleaner regroupe ses regles en categories. Voici les plus importantes :

1. Empty Lines - Optimiser les lignes vides

Regroupement intelligent des blocs de code :

Avant :

METHOD process_order.
DATA lv_status TYPE string.
DATA lv_amount TYPE p DECIMALS 2.
SELECT SINGLE status
FROM zorders
INTO lv_status
WHERE order_id = iv_order_id.
IF lv_status = 'OPEN'.
lv_amount = calculate_total( ).
update_order( lv_amount ).
ENDIF.
ENDMETHOD.

Apres :

METHOD process_order.
DATA lv_status TYPE string.
DATA lv_amount TYPE p DECIMALS 2.
SELECT SINGLE status
FROM zorders
INTO lv_status
WHERE order_id = iv_order_id.
IF lv_status = 'OPEN'.
lv_amount = calculate_total( ).
update_order( lv_amount ).
ENDIF.
ENDMETHOD.

2. Declarations - Moderniser les declarations

Avant :

DATA: lv_count TYPE i,
lt_items TYPE TABLE OF zitem,
ls_item TYPE zitem,
lo_processor TYPE REF TO zcl_processor.
CREATE OBJECT lo_processor.
CLEAR lt_items.

Apres :

DATA lv_count TYPE i.
DATA lt_items TYPE TABLE OF zitem.
DATA ls_item TYPE zitem.
DATA lo_processor TYPE REF TO zcl_processor.
lo_processor = NEW #( ).
CLEAR lt_items.

3. Syntax - Utiliser la syntaxe ABAP moderne

Avant :

CALL METHOD lo_service->get_data
EXPORTING
iv_id = lv_id
RECEIVING
rt_data = lt_data.
IF lt_data IS INITIAL.
" ...
ENDIF.
LOOP AT lt_data INTO ls_data.
MOVE-CORRESPONDING ls_data TO ls_result.
APPEND ls_result TO lt_result.
ENDLOOP.

Apres :

lt_data = lo_service->get_data( iv_id = lv_id ).
IF lt_data IS INITIAL.
" ...
ENDIF.
LOOP AT lt_data INTO DATA(ls_data).
lt_result = VALUE #( BASE lt_result ( CORRESPONDING #( ls_data ) ) ).
ENDLOOP.

4. Commands - Supprimer les commandes superflues

Avant :

CLEAR lv_result.
lv_result = calculate_value( ).
IF sy-subrc = 0.
" Succes
ENDIF.
MOVE lv_source TO lv_target.

Apres :

lv_result = calculate_value( ).
IF sy-subrc = 0.
" Succes
ENDIF.
lv_target = lv_source.

5. Alignment - Ameliorer l’alignement

Avant :

ls_order-order_id = lv_id.
ls_order-customer = lv_customer.
ls_order-status = 'NEW'.
ls_order-created_at = sy-datum.
ls_order-created_by = sy-uname.
ls_order-amount = lv_amount.

Apres :

ls_order-order_id = lv_id.
ls_order-customer = lv_customer.
ls_order-status = 'NEW'.
ls_order-created_at = sy-datum.
ls_order-created_by = sy-uname.
ls_order-amount = lv_amount.

6. Pretty Print - Formatage

Avant :

IF LV_STATUS='OPEN'AND LV_AMOUNT>100.
CALL METHOD LO_SERVICE->PROCESS(EXPORTING IV_ID=LV_ID CHANGING CT_DATA=LT_DATA).
ENDIF.

Apres :

IF lv_status = 'OPEN' AND lv_amount > 100.
lo_service->process( EXPORTING iv_id = lv_id
CHANGING ct_data = lt_data ).
ENDIF.

7. Inline Declarations - Utiliser VALUE et NEW

Avant :

DATA lt_orders TYPE TABLE OF zorder.
DATA ls_order TYPE zorder.
DATA lo_service TYPE REF TO zcl_order_service.
CREATE OBJECT lo_service
EXPORTING
iv_client = sy-mandt.
ls_order-order_id = '12345'.
ls_order-status = 'NEW'.
APPEND ls_order TO lt_orders.

Apres :

DATA(lo_service) = NEW zcl_order_service( iv_client = sy-mandt ).
DATA(lt_orders) = VALUE zorders_t(
( order_id = '12345' status = 'NEW' )
).

8. Comments - Formater les commentaires

Avant :

"Cette methode calcule le prix total
"TVA et remise incluses.
"Parametre: iv_net_price - Prix net
" iv_discount - Remise en pourcentage
"Retour: Prix brut
METHOD calculate_gross_price.

Apres :

" Cette methode calcule le prix total
" TVA et remise incluses.
" Parametre: iv_net_price - Prix net
" iv_discount - Remise en pourcentage
" Retour: Prix brut
METHOD calculate_gross_price.

Configuration et profils

Concept de profil

ABAP Cleaner utilise des profils pour la configuration. Un profil definit quelles regles sont actives et comment elles sont appliquees.

┌──────────────────────────────────────────────────────────────┐
│ Gestionnaire de profils │
├──────────────────────────────────────────────────────────────┤
│ │
│ Profils : │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ [★] Default │ │
│ │ [ ] Team Standard │ │
│ │ [ ] Strict Modernization │ │
│ │ [ ] Minimal Changes │ │
│ │ [ ] + Creer un nouveau profil... │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ [ Edit ] [ Copy ] [ Delete ] [ Export ] [ Import ] │
│ │
└──────────────────────────────────────────────────────────────┘

Creer et configurer un profil

  1. Window - Preferences - ABAP Cleaner ouvrir
  2. Profiles selectionner
  3. Create new profile cliquer

Configuration des regles

Chaque regle peut etre configuree individuellement :

┌──────────────────────────────────────────────────────────────┐
│ Configuration de regle : "Use inline declarations" │
├──────────────────────────────────────────────────────────────┤
│ │
│ ☑ Regle activee │
│ │
│ Options : │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Convertir les declarations DATA : │ │
│ │ ○ Uniquement si utilise une fois │ │
│ │ ● Si utilise dans le meme bloc │ │
│ │ ○ Toujours (agressif) │ │
│ │ │ │
│ │ ☑ Convertir FIELD-SYMBOLS │ │
│ │ ☑ Garder les declarations pour les types complexes │ │
│ │ ☐ Convertir meme si le type est perdu │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ Apercu : │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ DATA lv_name TYPE │ │ DATA(lv_name) = │ │
│ │ string. │→│ get_name( ). │ │
│ │ lv_name = get_name( │ │ │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘

Exporter et partager un profil

Les profils peuvent etre exportes en fichier JSON et partages dans l’equipe :

{
"profileName": "Team Standard",
"rules": {
"EmptyLinesInClassDefinition": {
"enabled": true,
"maxEmptyLines": 1
},
"UseInlineDeclaration": {
"enabled": true,
"convertFieldSymbols": true,
"onlyIfUsedOnce": false
},
"ReplaceCreateObject": {
"enabled": true
},
"RemoveUnusedVariables": {
"enabled": false
}
}
}

Distribution dans l’equipe :

1. Exporter le profil : Preferences → ABAP Cleaner → Export Profile
2. Placer le fichier JSON dans le depot Git : /config/abap-cleaner-profile.json
3. Les membres de l'equipe importent : Preferences → ABAP Cleaner → Import Profile

Utilisation au quotidien

Mode interactif

Le mode interactif montre tous les changements avant l’application :

Raccourci : Ctrl+4 (ou Source → Clean Up With Interactive ABAP Cleaner...)
┌──────────────────────────────────────────────────────────────┐
│ ABAP Cleaner interactif │
├──────────────────────────────────────────────────────────────┤
│ │
│ Regle : "Replace obsolete ADD with modern syntax" │
│ │
│ ┌─────────────────────────────┬─────────────────────────┐ │
│ │ Avant │ Apres │ │
│ ├─────────────────────────────┼─────────────────────────┤ │
│ │ ADD 1 TO lv_count. │ lv_count += 1. │ │
│ │ ADD lv_amount TO lv_total. │ lv_total += lv_amount. │ │
│ └─────────────────────────────┴─────────────────────────┘ │
│ │
│ [✓ Appliquer] [✗ Ignorer] [Tout appliquer] [Tout ignorer] │
│ │
│ Changements : 2 sur 15 appliques | Profil : Team Standard │
│ │
└──────────────────────────────────────────────────────────────┘

Mode automatique

Appliquer toutes les regles sans confirmation :

Raccourci : Ctrl+Shift+4 (ou Source → Clean Up With Automatic ABAP Cleaner)

Nettoyage a la sauvegarde

ABAP Cleaner peut etre execute automatiquement a chaque sauvegarde :

Preferences → ABAP Cleaner → Clean-up on save
☑ Activer le nettoyage a la sauvegarde
Profil : [Team Standard ▼]
Portee :
○ Methode courante uniquement
● Blocs de code modifies
○ Tout le code source
☑ Afficher une notification apres le nettoyage

Configurer les raccourcis clavier

Window → Preferences → General → Keys
Recherche : "ABAP Cleaner"
Resultats :
- Clean Up With Interactive ABAP Cleaner : Ctrl+4
- Clean Up With Automatic ABAP Cleaner : Ctrl+Shift+4
- Open ABAP Cleaner Preferences : Ctrl+Shift+Alt+4

Exemple complet avant/apres

Avant : Code legacy

CLASS zcl_order_processor DEFINITION
PUBLIC
FINAL
CREATE PUBLIC.
PUBLIC SECTION.
METHODS: process_order
IMPORTING
iv_order_id TYPE zorder_id
RETURNING
VALUE(rv_success) TYPE abap_bool
RAISING
zcx_order_error.
PRIVATE SECTION.
DATA: mv_client TYPE mandt.
DATA: mo_logger TYPE REF TO zcl_logger.
ENDCLASS.
CLASS zcl_order_processor IMPLEMENTATION.
METHOD process_order.
DATA: lv_status TYPE zorder_status,
lt_items TYPE TABLE OF zorder_item,
ls_item TYPE zorder_item,
lv_total TYPE p DECIMALS 2,
lo_validator TYPE REF TO zcl_order_validator.
CREATE OBJECT lo_validator.
CLEAR lv_total.
SELECT SINGLE status
FROM zorders
INTO lv_status
WHERE order_id EQ iv_order_id.
IF sy-subrc NE 0.
RAISE EXCEPTION TYPE zcx_order_error.
ENDIF.
IF lv_status EQ 'CLOSED'.
rv_success = abap_false.
RETURN.
ENDIF.
SELECT *
FROM zorder_items
INTO TABLE lt_items
WHERE order_id EQ iv_order_id.
LOOP AT lt_items INTO ls_item.
ADD ls_item-amount TO lv_total.
ENDLOOP.
CALL METHOD lo_validator->validate
EXPORTING
iv_order_id = iv_order_id
iv_total = lv_total
RECEIVING
rv_valid = DATA(lv_valid).
IF lv_valid EQ abap_true.
UPDATE zorders SET status = 'PROCESSING' WHERE order_id = iv_order_id.
rv_success = abap_true.
ELSE.
rv_success = abap_false.
ENDIF.
ENDMETHOD.
ENDCLASS.

Apres : Code modernise

CLASS zcl_order_processor DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
METHODS process_order
IMPORTING iv_order_id TYPE zorder_id
RETURNING VALUE(rv_success) TYPE abap_bool
RAISING zcx_order_error.
PRIVATE SECTION.
DATA mv_client TYPE mandt.
DATA mo_logger TYPE REF TO zcl_logger.
ENDCLASS.
CLASS zcl_order_processor IMPLEMENTATION.
METHOD process_order.
DATA(lo_validator) = NEW zcl_order_validator( ).
SELECT SINGLE status
FROM zorders
INTO @DATA(lv_status)
WHERE order_id = @iv_order_id.
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE zcx_order_error.
ENDIF.
IF lv_status = 'CLOSED'.
rv_success = abap_false.
RETURN.
ENDIF.
SELECT *
FROM zorder_items
INTO TABLE @DATA(lt_items)
WHERE order_id = @iv_order_id.
DATA(lv_total) = REDUCE #( INIT sum = 0
FOR ls_item IN lt_items
NEXT sum += ls_item-amount ).
DATA(lv_valid) = lo_validator->validate( iv_order_id = iv_order_id
iv_total = lv_total ).
IF lv_valid = abap_true.
UPDATE zorders SET status = 'PROCESSING' WHERE order_id = iv_order_id.
rv_success = abap_true.
ELSE.
rv_success = abap_false.
ENDIF.
ENDMETHOD.
ENDCLASS.

Resume des changements

CategorieChangement
Lignes videsLignes vides superflues supprimees, regroupement logique
DeclarationsDeclarations DATA: chainees separees
CREATE OBJECTRemplace par NEW #( )
CLEARCLEAR inutile supprime (variable assignee directement)
CALL METHODEcriture fonctionnelle utilisee
EQ/NERemplace par =/<>
Inline DATADeclarations inline ou pertinentes
REDUCELOOP AT avec ADD remplace par REDUCE
AlignmentAlignement coherent des parametres

Integration dans CI/CD

ABAP Cleaner peut etre utilise comme partie du pipeline CI/CD pour verifier les standards de code :

.github/workflows/abap-style.yml
name: ABAP Style Check
on:
pull_request:
paths:
- 'src/**.abap"
jobs:
style-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '11"
distribution: 'temurin"
- name: Run ABAP Cleaner Check
run: |
# Telecharger ABAP Cleaner CLI
wget https://github.com/SAP/abap-cleaner/releases/latest/download/abap-cleaner-cli.jar
# Verifier si des modifications de nettoyage seraient necessaires
java -jar abap-cleaner-cli.jar \
--profile config/abap-cleaner-profile.json \
--check-only \
--source src/
- name: Upload Report
if: failure()
uses: actions/upload-artifact@v4
with:
name: cleanup-report
path: cleanup-report.txt

Bonnes pratiques

ThemeRecommandation
Selection du profilCommencer avec le profil par defaut, ajuster progressivement
Standard d’equipeDefinir un profil commun pour toute l’equipe
Cleanup on SaveActiver pour un code coherent
Mode interactifVerifier d’abord de maniere interactive pour le code legacy
Revue de codeEffectuer le nettoyage avant la revue
Nouvelles reglesVerifier les nouvelles regles lors des mises a jour d’ABAP Cleaner
ExceptionsRegles desactivables pour des fichiers specifiques
CI/CDIntegrer comme verification de style dans le pipeline
MigrationNettoyer le code legacy progressivement, pas tout a la fois
DocumentationDocumenter les decisions de profil d’equipe

Sujets connexes