Skip to content
Merged
1,088 changes: 1,088 additions & 0 deletions src/checks/#cc4a#modern_language.clas.abap

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions src/checks/#cc4a#modern_language.clas.locals_def.abap
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*"* use this source file for any type of declarations (class
*"* definitions, interfaces or type declarations) you need for
*"* components in the private section
class lcx_error definition final
inheriting from cx_static_check.
endclass.
6 changes: 6 additions & 0 deletions src/checks/#cc4a#modern_language.clas.locals_imp.abap
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*"* use this source file for the definition and implementation of
*"* local helper classes, interface definitions and type
*"* declarations

class lcx_error implementation.
endclass.
426 changes: 426 additions & 0 deletions src/checks/#cc4a#modern_language.clas.testclasses.abap

Large diffs are not rendered by default.

121 changes: 121 additions & 0 deletions src/checks/#cc4a#modern_language.clas.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<abapGit version="v1.0.0" serializer="LCL_OBJECT_CLAS" serializer_version="v1.0.0">
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
<VSEOCLASS>
<CLSNAME>/CC4A/MODERN_LANGUAGE</CLSNAME>
<LANGU>E</LANGU>
<DESCRIPT>check for modern language</DESCRIPT>
<STATE>1</STATE>
<CLSCCINCL>X</CLSCCINCL>
<FIXPT>X</FIXPT>
<UNICODE>X</UNICODE>
<WITH_UNIT_TESTS>X</WITH_UNIT_TESTS>
</VSEOCLASS>
<TPOOL>
<item>
<ID>I</ID>
<KEY>001</KEY>
<ENTRY>MOVE is obsolete</ENTRY>
<LENGTH>26</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>002</KEY>
<ENTRY>TRANSLATE TO UPPER/LOWERCASE is obsolete</ENTRY>
<LENGTH>80</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>003</KEY>
<ENTRY>Prefer LINE_EXISTS/LINE_INDEX</ENTRY>
<LENGTH>50</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>004</KEY>
<ENTRY>Prefer NEW instead of CREATE OBJECT</ENTRY>
<LENGTH>70</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>005</KEY>
<ENTRY>Prefer functional call instead of CALL METHOD</ENTRY>
<LENGTH>90</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>006</KEY>
<ENTRY>Omit EXPORTING in functional Method Call if possible</ENTRY>
<LENGTH>104</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>007</KEY>
<ENTRY>Do not use RECEIVING in functional Method Call if possible</ENTRY>
<LENGTH>116</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>008</KEY>
<ENTRY>Use string templates instead of &amp;&amp;</ENTRY>
<LENGTH>68</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>DES</KEY>
<ENTRY>Modern Language</ENTRY>
<LENGTH>25</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>QF1</KEY>
<ENTRY>Replace MOVE statement</ENTRY>
<LENGTH>44</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>QF2</KEY>
<ENTRY>Replace TRANSLATE statement</ENTRY>
<LENGTH>54</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>QF3</KEY>
<ENTRY>Use LINE_EXISTS/LINE_INDEX</ENTRY>
<LENGTH>52</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>QF4</KEY>
<ENTRY>Use NEW instead of CREATE OBJECT</ENTRY>
<LENGTH>64</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>QF5</KEY>
<ENTRY>Use functional call instead of CALL METHOD</ENTRY>
<LENGTH>84</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>QF6</KEY>
<ENTRY>Omit EXPORTING</ENTRY>
<LENGTH>24</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>QF7</KEY>
<ENTRY>Do not use EXPORTING/RECEIVING</ENTRY>
<LENGTH>60</LENGTH>
</item>
<item>
<ID>I</ID>
<KEY>QF8</KEY>
<ENTRY>Replace &amp;&amp; by string templates</ENTRY>
<LENGTH>60</LENGTH>
</item>
</TPOOL>
</asx:values>
</asx:abap>
</abapGit>
10 changes: 10 additions & 0 deletions src/checks/(cc4a)modern.chko.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"formatVersion": "1",
"header": {
"description": "Modern Language",
"originalLanguage": "en"
},
"category": "/CC4A/CODE_PAL",
"implementingClass": "/CC4A/MODERN_LANGUAGE",
"checkType": "remoteEnabled"
}
117 changes: 98 additions & 19 deletions src/core/#cc4a#abap_analyzer.clas.abap
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class /cc4a/abap_analyzer definition
aliases is_token_keyword for /cc4a/if_abap_analyzer~is_token_keyword.
aliases is_db_statement for /cc4a/if_abap_analyzer~is_db_statement.
aliases is_bracket for /cc4a/if_abap_analyzer~is_bracket.
aliases max_line_length for /cc4a/if_abap_analyzer~max_line_length.

protected section.
private section.

Expand All @@ -23,30 +25,28 @@ class /cc4a/abap_analyzer definition
class-data negations type table of ty_negation.

methods _flatten_tokens
changing tokens type if_ci_atc_source_code_provider=>ty_tokens
changing tokens type if_ci_atc_source_code_provider=>ty_tokens
returning value(flat) type string.

methods _flatten_template
changing tokens type if_ci_atc_source_code_provider=>ty_tokens
changing tokens type if_ci_atc_source_code_provider=>ty_tokens
returning value(flat) type string.
ENDCLASS.

methods _break_into_lines
importing value(code) type string
break_at type i
returning value(code_lines) type string_table
raising /cc4a/cx_line_break_impossible.

endclass.



CLASS /CC4A/ABAP_ANALYZER IMPLEMENTATION.
class /cc4a/abap_analyzer implementation.


method /cc4a/if_abap_analyzer~break_into_lines.
constants allowed_line_length type i value 255.
data(remaining_chunk) = strlen( code ).
while remaining_chunk > 0.
data(already_chopped_chars) = lines( code_lines ) * allowed_line_length.
data(chars_to_chop) = cond #(
when remaining_chunk > allowed_line_length
then allowed_line_length
else remaining_chunk ).
insert code+already_chopped_chars(chars_to_chop) into table code_lines.
remaining_chunk -= chars_to_chop.
endwhile.
code_lines = _break_into_lines( code = code break_at = max_line_length ).
endmethod.


Expand Down Expand Up @@ -284,6 +284,7 @@ CLASS /CC4A/ABAP_ANALYZER IMPLEMENTATION.

endmethod.


method _flatten_tokens.
if not line_exists( tokens[ lexeme = '|' ] ).
flat = reduce #( init str = `` for tok in tokens next str = |{ str }{ tok-lexeme } | ).
Expand All @@ -292,18 +293,23 @@ CLASS /CC4A/ABAP_ANALYZER IMPLEMENTATION.
while lines( tokens ) > 0.
if <token>-lexeme = '|'.
delete tokens index 1.
flat &&= |\|{ _flatten_template( changing tokens = tokens ) }\||.
data(template) = _flatten_template( changing tokens = tokens ).
flat &&= |\|{ template }\| |.
else.
flat &&= |{ <token>-lexeme } |.
delete tokens index 1.
endif.
delete tokens index 1.
assign tokens[ 1 ] to <token>.
endwhile.
endif.
data(len) = strlen( flat ) - 1.
if flat+len(1) = ` `.
flat = flat(len).
endif.
endmethod.

method _flatten_template.
data(inside_braces) = abap_true.
data(inside_braces) = abap_false.
assign tokens[ 1 ] to field-symbol(<token>).
while lines( tokens ) > 0.
case <token>-lexeme.
Expand Down Expand Up @@ -339,4 +345,77 @@ CLASS /CC4A/ABAP_ANALYZER IMPLEMENTATION.
endwhile.
endmethod.

ENDCLASS.


method _break_into_lines.
data i type i.
data in_sqmarks type abap_bool.
data in_quotes type abap_bool.
data in_template type abap_bool.
data in_braces type abap_bool.
data last_space type i.
if strlen( code ) <= break_at.
code_lines = value #( ( code ) ).
return.
endif.

while i < strlen( code ).
case code+i(1).
when '`'.
if in_quotes = abap_false and in_template = abap_false.
in_sqmarks = cond #( when in_sqmarks = abap_false then abap_true else abap_false ).
endif.
when `'`.
if in_sqmarks = abap_false and in_template = abap_false.
in_quotes = cond #( when in_quotes = abap_false then abap_true else abap_false ).
endif.
when '|'.
if in_sqmarks = abap_false and in_quotes = abap_false.
in_template = cond #( when in_template = abap_false then abap_true else abap_false ).
endif.
when `\`.
i += 1.
when '{'.
if in_template = abap_true and in_sqmarks = abap_false and in_quotes = abap_false.
in_braces = abap_true.
endif.
when '}'.
if in_template = abap_true and in_sqmarks = abap_false and in_quotes = abap_false.
in_braces = abap_false.
endif.
when ` `.
if in_sqmarks = abap_false and in_quotes = abap_false and
( in_template = abap_false or in_braces = abap_true ).
last_space = i.
endif.
endcase.
i += 1.
if i > break_at.
if last_space = 0.
raise exception type /cc4a/cx_line_break_impossible.
else.
append code(last_space) to code_lines.
last_space += 1.
if last_space >= strlen( code ).
return.
endif.
code = code+last_space.
if strlen( code ) <= break_at.
append code to code_lines.
return.
endif.
i = 0.
last_space = 0.
in_sqmarks = abap_false.
in_quotes = abap_false.
in_template = abap_false.
endif.
endif.
endwhile.
if i > break_at.
raise exception type /cc4a/cx_line_break_impossible.
else.
append code to code_lines.
endif.
endmethod.
endclass.
7 changes: 2 additions & 5 deletions src/core/#cc4a#abap_analyzer.clas.locals_imp.abap
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
*"* use this source file for the definition and implementation of
*"* local helper classes, interface definitions and type
*"* declarations
class db_statement_analyzer definition deferred.
class /cc4a/abap_analyzer definition local friends db_statement_analyzer.
class db_statement_analyzer definition final.
Expand Down Expand Up @@ -164,12 +161,12 @@ class db_statement_analyzer implementation.
if lines( token_db-references ) > 1.
result-is_db = abap_false.
* no symbol - so try okay
elseif <ref1>-full_name(3) = '\' && tag_type.
elseif <ref1>-full_name(3) = |\\{ tag_type }|.
result-is_db = abap_true.
endif.
when if_ci_atc_source_code_provider=>compiler_reference_kinds-data.
result-is_db = abap_false.
if token_db-references[ 1 ]-full_name(3) = '\' && tag_common_part.
if token_db-references[ 1 ]-full_name(3) = |\\{ tag_common_part }|.
split token_db-references[ 1 ]-full_name+4 at |\\{ tag_data }:| into data(l_name1) data(l_name2).
if l_name1 = l_name2.
result-is_db = abap_true.
Expand Down
Loading