Advertisement
rplantiko

Demeter Law Violation Detector

Jul 7th, 2012
467
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
ABAP 7.40 KB | None | 0 0
  1. *&---------------------------------------------------------------------*
  2. *& Report  ZZ_CHECK_DEMETER_LAW
  3. *&---------------------------------------------------------------------*
  4. *& Checks ABAP method code for the easiest type of LoD violation
  5. *& Extensible by more cases
  6. *&---------------------------------------------------------------------*
  7.  
  8. report  zz_check_demeter_law.
  9.  
  10. parameters: p_class type seomtdkey-clsname,  " Structure has F4 attached!
  11.             p_meth  type seomtdkey-mtdname.  " Structure has F4 attached!
  12.  
  13. start-of-selection.
  14.   perform start.
  15.  
  16. * ---
  17. class lcl_scanner definition.
  18.   public section.
  19.     methods:
  20.       constructor importing it_source type stringtab
  21.                   raising cx_abap_error_analyze,
  22.       get_first_token importing is_stmnt type sstmnt
  23.                       returning value(ev_token) type char30,
  24.       get_second_token importing is_stmnt type sstmnt
  25.                        returning value(ev_token) type char30,
  26.       get_nth_token importing iv_n type i
  27.                               is_stmnt type sstmnt
  28.                     returning value(ev_token) type char30,
  29.       get_first_stmnt importing iv_first_token type char30
  30.                 returning value(es_stmnt) type sstmnt,
  31.       get_stmnts importing iv_first_token type char30
  32.                 returning value(et_stmnt) type sstmnt_tab,
  33.       to_string importing is_stmnt type sstmnt
  34.                 exporting ev_stmnt type string.
  35.     data: gt_token type stokes_tab read-only,
  36.           gt_stmnt type sstmnt_tab read-only.
  37. endclass.                    "lcl_scanner DEFINITION
  38.  
  39. * ---
  40. class lcl_check_demeter definition.
  41.   public section.
  42.     data: gs_key       type seocpdkey,
  43.           go_descr     type ref to cl_abap_classdescr read-only,
  44.           gt_methcode  type stringtab read-only,
  45.           go_scanner   type ref to lcl_scanner.
  46.     methods:
  47.       constructor importing iv_class type seoclsname
  48.                             iv_meth  type seocpdname
  49.                   raising cx_abap_error_analyze,
  50.       get_classdescr returning value(eo_descr) type ref to cl_abap_typedescr
  51.                      raising cx_abap_error_analyze,
  52.       read_method raising cx_abap_error_analyze,
  53.       read_source exporting et_methcode type stringtab
  54.                   raising cx_abap_error_analyze,
  55.       scan_source importing it_methcode type stringtab
  56.                   exporting eo_scanner type ref to lcl_scanner
  57.                   raising cx_abap_error_analyze,
  58.       check raising cx_abap_error_analyze .
  59. endclass.                    "lcl_check_demeter DEFINITION
  60.  
  61. * ---
  62. form start.
  63.  
  64.   data: lo_demeter type ref to lcl_check_demeter,
  65.         lo_ex      type ref to cx_abap_error_analyze .
  66.  
  67.   try.
  68.       create object lo_demeter
  69.         exporting
  70.           iv_class = p_class
  71.           iv_meth  = p_meth.
  72.  
  73.       lo_demeter->check( ).
  74.  
  75.     catch cx_abap_error_analyze  into lo_ex.
  76.       message lo_ex->message type 'I'.
  77.   endtry.
  78.  
  79.  
  80. endform.                    "start
  81.  
  82.  
  83. * ---
  84. class lcl_check_demeter implementation.
  85.   method constructor.
  86.     gs_key-clsname = iv_class.
  87.     gs_key-cpdname = iv_meth.
  88.     go_descr ?= get_classdescr( ).
  89.     read_method(  ).
  90.   endmethod.                    "constructor
  91.   method get_classdescr.
  92.     call method cl_abap_classdescr=>describe_by_name
  93.       exporting
  94.         p_name      = gs_key-clsname
  95.       receiving
  96.         p_descr_ref = eo_descr
  97.       exceptions
  98.         others      = 1.
  99.     if sy-subrc ne 0.
  100.       raise exception type cx_abap_error_analyze
  101.         exporting
  102.           message = 'Class not found'.
  103.     endif.
  104.   endmethod.                    "get_classdescr
  105.   method read_method.
  106.     read_source( importing et_methcode = gt_methcode ).
  107.     scan_source( exporting it_methcode = gt_methcode
  108.                  importing eo_scanner  = go_scanner ).
  109.   endmethod.                    "read_method
  110.   method read_source.
  111.  
  112.     data: lv_msg type string.
  113.  
  114.     call function 'SEO_METHOD_GET_SOURCE'
  115.       exporting
  116.         mtdkey                        = gs_key
  117.       importing
  118.         source_expanded               = et_methcode
  119.       exceptions
  120.         _internal_method_not_existing = 1
  121.         _internal_class_not_existing  = 2
  122.         version_not_existing          = 3
  123.         inactive_new                  = 4
  124.         inactive_deleted              = 5
  125.         others                        = 6.
  126.  
  127.     if sy-subrc <> 0.
  128.       message id sy-msgid type sy-msgty number sy-msgno
  129.         with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
  130.         into lv_msg.
  131.       raise exception type cx_abap_error_analyze
  132.         exporting
  133.           message = lv_msg.
  134.     endif.
  135.  
  136.   endmethod.                    "read_method
  137.   method scan_source.
  138.     create object eo_scanner
  139.       exporting
  140.         it_source = it_methcode.
  141.   endmethod.                    "scan_source
  142.   method check.
  143.  
  144.     data: lv_stmnt type string,
  145.           lv_msg   type string.
  146.  
  147.     field-symbols: <ls_stmnt> type sstmnt,
  148.                    <ls_token> type stokes.
  149.  
  150.     loop at go_scanner->gt_token assigning <ls_token>.
  151.       if <ls_token>-str cp '*->*->*'.
  152.         concatenate `'` <ls_token>-str `'` into lv_msg.
  153.         concatenate 'Demeter violation' lv_msg into lv_msg
  154.           separated by space.
  155.         raise exception type cx_abap_error_analyze
  156.           exporting
  157.             message = lv_msg.
  158.       endif.
  159.     endloop.
  160.  
  161.   endmethod.                    "check
  162. endclass.                    "lcl_check_demeter IMPLEMENTATION
  163.  
  164.  
  165. * ---
  166. class lcl_scanner implementation.
  167.   method get_nth_token.
  168.     field-symbols: <ls_token> type stokes.
  169.     data: lv_index type i.
  170.     lv_index = iv_n - 1 + is_stmnt-from.
  171.     read table gt_token assigning <ls_token> index lv_index.
  172.     if sy-subrc eq 0.
  173.       ev_token = <ls_token>-str.
  174.     endif.
  175.   endmethod.                    "get_nth_token
  176.   method get_first_token.
  177.     ev_token = get_nth_token( iv_n = 1 is_stmnt = is_stmnt ).
  178.   endmethod.                    "get_first_token
  179.   method get_second_token.
  180.     ev_token = get_nth_token( iv_n = 2 is_stmnt = is_stmnt ).
  181.   endmethod.                    "get_second_token
  182.   method constructor.
  183.     data: lv_msg type string.
  184.     scan abap-source it_source
  185.       tokens into gt_token
  186.       statements into gt_stmnt
  187.       message into lv_msg.
  188.  
  189.     if sy-subrc ne 0.
  190.       if lv_msg is initial.
  191.         lv_msg = 'Scanner error'.
  192.       endif.
  193.       raise exception type cx_abap_error_analyze
  194.         exporting
  195.           message = lv_msg.
  196.     endif.
  197.   endmethod.                    "constructor
  198.   method get_first_stmnt.
  199.     data: lt_stmnts type sstmnt_tab.
  200.     lt_stmnts = get_stmnts( iv_first_token ).
  201.     read table lt_stmnts into es_stmnt index 1.
  202.   endmethod.                    "get_first_stmnt
  203.   method get_stmnts.
  204.     field-symbols: <ls_stmnt> type sstmnt.
  205.     loop at gt_stmnt assigning <ls_stmnt>.
  206.       if get_first_token( <ls_stmnt> ) cp iv_first_token. " cp, not eq, for being case-insensitive
  207.         insert <ls_stmnt> into table et_stmnt.
  208.       endif.
  209.     endloop.
  210.   endmethod.                    "get_stmnts
  211.   method to_string.
  212.     field-symbols: <ls_token> type stokes.
  213.     clear ev_stmnt.
  214.     loop at gt_token assigning <ls_token>
  215.                      from is_stmnt-from
  216.                        to is_stmnt-to.
  217.       concatenate ev_stmnt <ls_token>-str into ev_stmnt
  218.         separated by space.
  219.     endloop.
  220.   endmethod.
  221. endclass.                    "lcl_scanner IMPLEMENTATION
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement