├── .abapgit.xml
├── LICENSE
├── README.md
├── package.devc.xml
├── z_debug_obj_service_graph.enho.xml
├── z_debug_obj_service_graph_var.enho.xml
├── zcl_debug_obj_graph_factory.clas.abap
├── zcl_debug_obj_graph_factory.clas.locals_def.abap
├── zcl_debug_obj_graph_factory.clas.locals_imp.abap
├── zcl_debug_obj_graph_factory.clas.xml
├── zcl_debug_obj_to_graph.clas.abap
└── zcl_debug_obj_to_graph.clas.xml
/.abapgit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | E
6 | /
7 | PREFIX
8 |
9 | - /.gitignore
10 | - /LICENSE
11 | - /README.md
12 | - /package.json
13 | - /.travis.yml
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Marcello Urbani
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Abap debugger object graph extension
2 |
3 | ABAP debugger extension to visualize objects as graphs via [graphviz](http://www.graphviz.org/)
4 |
5 | ### Installation
6 |
7 | The prerequisite [ABAP Graph](https://github.com/marcellourbani/abapgraph) needs to be installed first, then install via [abapGit](https://github.com/larshp/abapGit)
8 |
9 | Tested on netweaver 7.5, not sure about older releases
10 |
11 | ### Use
12 |
13 | 1. Set breakpoint in source code
14 | 2. In the new debugger go to "Objects" tab
15 | 3. open the tools menu from the icon on the left 
16 |
17 | 4. select **View object as graph**
18 |
19 | The object graph will be shown in a new browser window (Example from http://zevolving.com/2012/01/iterator-design-pattern-to-access-linked-list/ )
20 |
21 | 
22 |
23 | Another example from the excellent [Writing Testable Code for ABAP](https://open.sap.com/courses/wtc1) opensap course
24 | 
25 |
26 | Originally inspired by
27 | [ABAP-Object-Visualizer](https://github.com/larshp/ABAP-Object-Visualizer)
28 |
29 | Uses [Graphviz-browser](https://github.com/marcellourbani/Graphviz-browser) to render the graph in a browser window
30 |
--------------------------------------------------------------------------------
/package.devc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Object graph viewer for debug tool
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/z_debug_obj_service_graph.enho.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HOOK_IMPL
6 | Graph display for object
7 |
8 | R3TR
9 | CLAS
10 | CL_TPDA_TOOL_OBJECT_VIEW
11 | CLAS
12 | CL_TPDA_TOOL_OBJECT_VIEW
13 | CL_TPDA_TOOL_OBJECT_VIEW======CP
14 |
15 |
16 |
17 | CL_TPDA_TOOL_OBJECT_VIEW======CP
18 | 1
19 | 1
20 | D
21 | \TY:CL_TPDA_TOOL_OBJECT_VIEW\IN:IF_TPDA_TOOL_SERVICES\ME:BUILD_SERVICES_MENUE\SE:END\EI
22 |
23 | - DATA l_zz_node LIKE LINE OF p_it_menue_tree.
24 | - CLEAR l_zz_node.
25 |
26 | - l_zz_node-node_key = 'ZOBJEXPORTGR'.
27 | - l_zz_node-relatkey = cl_tpda_services_tools=>c_special.
28 | - l_zz_node-n_image = cl_tpda_icons=>TPDA_ICON_EDITOR_VIEW.
29 | - l_zz_node-relatship = cl_gui_simple_tree=>relat_last_child.
30 | - l_zz_node-text = 'View object as graph'.
31 |
32 | - APPEND l_zz_node TO p_it_menue_tree.
33 |
34 |
35 |
36 | CL_TPDA_TOOL_OBJECT_VIEW======CP
37 | 2
38 | 2
39 | D
40 | \TY:CL_TPDA_TOOL_OBJECT_VIEW\IN:IF_TPDA_TOOL_SERVICES\ME:HANDLE_SERVICE_REQUEST\SE:BEGIN\EI
41 |
42 | - data: zzl_node_key like line of p_it_selected_node,
43 | - zdebgr type ref to ZCL_DEBUG_OBJ_TO_GRAPH,
44 | - zz_exception type ref to cx_root.
45 | - read table p_it_selected_node INTO zzl_node_key INDEX 1.
46 | - if zzl_node_key = 'ZOBJEXPORTGR'.
47 | - try.
48 | - create object zdebgr.
49 | - zdebgr->display_graph( dynp_vars-object_name_real ).
50 | - catch cx_sy_no_handler into zz_exception .
51 | - message zz_exception->previous type 'I'.
52 | - catch cx_root into zz_exception .
53 | - message zz_exception type 'I'.
54 | - endtry.
55 | - exit.
56 | - endif.
57 |
58 |
59 |
60 |
61 | -
62 | \TY:CL_TPDA_TOOL_OBJECT_VIEW\IN:IF_TPDA_TOOL_SERVICES\ME:BUILD_SERVICES_MENUE\SE:END\EI
63 |
64 |
- 1
65 | - 1
66 | - 0
67 | - 1
68 | - 1
69 | - 1
70 | - 1
71 | - 1
72 | - 0
73 | - 1
74 |
75 |
76 | -
77 | \TY:CL_TPDA_TOOL_OBJECT_VIEW\IN:IF_TPDA_TOOL_SERVICES\ME:HANDLE_SERVICE_REQUEST\SE:BEGIN\EI
78 |
79 |
- 2
80 | - 14
81 | - 14
82 | - 3
83 | - 4
84 | - 6
85 | - 8
86 | - 8
87 | - 4
88 | - 7
89 | - 4
90 | - 7
91 | - 4
92 | - 4
93 | - 2
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/z_debug_obj_service_graph_var.enho.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HOOK_IMPL
6 | Display variable graph
7 |
8 | R3TR
9 | CLAS
10 | CL_TPDA_TOOL_QUICK_VARS
11 | CLAS
12 | CL_TPDA_TOOL_QUICK_VARS
13 | CL_TPDA_TOOL_QUICK_VARS=======CP
14 |
15 |
16 |
17 | CL_TPDA_TOOL_QUICK_VARS=======CP
18 | 1
19 | 1
20 | D
21 | \TY:CL_TPDA_TOOL_QUICK_VARS\IN:IF_TPDA_TOOL_SERVICES\ME:BUILD_SERVICES_MENUE\SE:END\EI
22 |
23 | - DATA l_zz_node LIKE LINE OF p_it_menue_tree.
24 | - CLEAR l_zz_node.
25 |
26 | - l_zz_node-node_key = 'ZOBJEXPORTGR'.
27 | - l_zz_node-relatkey = cl_tpda_services_tools=>c_special.
28 | - l_zz_node-n_image = cl_tpda_icons=>TPDA_ICON_EDITOR_VIEW.
29 | - l_zz_node-relatship = cl_gui_simple_tree=>relat_last_child.
30 | - l_zz_node-text = 'View object as graph'.
31 |
32 | - APPEND l_zz_node TO p_it_menue_tree.
33 |
34 |
35 |
36 | CL_TPDA_TOOL_QUICK_VARS=======CP
37 | 2
38 | 2
39 | D
40 | \TY:CL_TPDA_TOOL_QUICK_VARS\IN:IF_TPDA_TOOL_SERVICES\ME:HANDLE_SERVICE_REQUEST\SE:BEGIN\EI
41 |
42 | - data: zzl_node_key like line of p_it_selected_node,
43 | - zdebgr type ref to ZCL_DEBUG_OBJ_TO_GRAPH,
44 | - zz_var_name type string,
45 | - zz_exception type ref to cx_root.
46 | - read table p_it_selected_node INTO zzl_node_key INDEX 1.
47 |
48 | - if zzl_node_key = 'ZOBJEXPORTGR'.
49 | - try.
50 | - create object zdebgr.
51 | - zz_var_name = zdebgr->popup( ).
52 | - if zz_var_name <> ''.
53 | - zdebgr->display_graph( zz_var_name ).
54 | - endif.
55 | - catch cx_sy_no_handler into zz_exception .
56 | - message zz_exception->previous type 'I'.
57 | - catch cx_root into zz_exception .
58 | - message zz_exception type 'I'.
59 | - endtry.
60 |
61 | - exit.
62 | - endif.
63 |
64 |
65 |
66 |
67 | -
68 | \TY:CL_TPDA_TOOL_QUICK_VARS\IN:IF_TPDA_TOOL_SERVICES\ME:BUILD_SERVICES_MENUE\SE:END\EI
69 |
70 |
- 1
71 | - 1
72 | - 0
73 | - 1
74 | - 1
75 | - 1
76 | - 1
77 | - 1
78 | - 0
79 | - 1
80 |
81 |
82 | -
83 | \TY:CL_TPDA_TOOL_QUICK_VARS\IN:IF_TPDA_TOOL_SERVICES\ME:HANDLE_SERVICE_REQUEST\SE:BEGIN\EI
84 |
85 |
- 2
86 | - 9
87 | - 9
88 | - 9
89 | - 3
90 | - 0
91 | - 3
92 | - 5
93 | - 8
94 | - 8
95 | - 8
96 | - 10
97 | - 8
98 | - 5
99 | - 7
100 | - 5
101 | - 7
102 | - 5
103 | - 0
104 | - 5
105 | - 3
106 |
107 |
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/zcl_debug_obj_graph_factory.clas.abap:
--------------------------------------------------------------------------------
1 | class zcl_debug_obj_graph_factory definition public final create public .
2 |
3 | public section.
4 | class-methods create importing i_max_tab_lines type i default 200
5 | returning value(r_result) type ref to zcl_debug_obj_graph_factory.
6 |
7 | methods: create_graph importing root type string
8 | returning value(graph) type ref to zcl_abap_graph.
9 |
10 | data: max_tab_lines type i read-only,
11 | logs type string read-only.
12 |
13 | private section.
14 | constants: c_headerbg type string value 'lavender',
15 | c_privatebg type string value 'lightsalmon',
16 | c_protectedbg type string value 'khaki'.
17 |
18 | types: begin of ty_type_desc,
19 | name type string,
20 | local type abap_bool,
21 | end of ty_type_desc,
22 | begin of ty_data_desc,
23 | name type string,
24 | descr type ref to cl_tpda_script_data_descr,
25 | refname type string,
26 | valuetext type string,
27 | typedesc type ty_type_desc,
28 | metatype type tpda_scr_quick_info-metatype,
29 | hascomponents type abap_bool,
30 | istable type abap_bool,
31 | isreference type abap_bool,
32 | haschildren type abap_bool,
33 | end of ty_data_desc,
34 | begin of ty_component,
35 | compname type string,
36 | value type string,
37 | desc type ty_data_desc,
38 | visibility type i,
39 | end of ty_component,
40 | tt_component type table of ty_component with default key.
41 |
42 | constants: c_public type i value 0,
43 | c_protected type i value 1,
44 | c_private type i value 2,
45 | c_dummy type string value 'DUMMY'.
46 | data: graph type ref to zcl_abap_graph.
47 |
48 | methods create_node_new importing desc type zcl_debug_obj_graph_factory=>ty_data_desc
49 | returning value(node) type ref to zif_abap_graph_node.
50 |
51 | methods get_or_create_node importing name type string
52 | returning value(nodeid) type string.
53 |
54 | methods get_node_id importing name type string
55 | returning value(id) type string.
56 |
57 |
58 | methods escapevalue importing original type string
59 | returning value(escaped) type string.
60 |
61 | methods get_data_desc importing name type string
62 | returning value(desc) type ty_data_desc.
63 |
64 | methods create_table_node importing desc type zcl_debug_obj_graph_factory=>ty_data_desc
65 | returning value(node) type ref to zif_abap_graph_node.
66 |
67 | methods create_record_node importing desc type zcl_debug_obj_graph_factory=>ty_data_desc
68 | returning value(node) type ref to zif_abap_graph_node.
69 |
70 | methods create_simple_node importing desc type zcl_debug_obj_graph_factory=>ty_data_desc
71 | returning value(node) type ref to zif_abap_graph_node.
72 |
73 | methods get_components importing desc type zcl_debug_obj_graph_factory=>ty_data_desc
74 | returning value(components) type zcl_debug_obj_graph_factory=>tt_component.
75 |
76 | methods log importing entry type string.
77 |
78 | methods add_record_component importing record type ref to zcl_abap_graph_node_record
79 | component type zcl_debug_obj_graph_factory=>ty_component
80 | returning value(componentid) type string.
81 |
82 | methods get_value importing desc type ty_data_desc
83 | returning value(r_result) type string.
84 |
85 | methods get_head_label importing desc type ty_data_desc
86 | returning value(r_result) type string.
87 |
88 | methods decode_visibility importing acckind type i
89 | returning value(r_result) type i.
90 |
91 | methods decodetype importing typename type string
92 | desc type ty_data_desc
93 | returning value(td) type ty_type_desc.
94 |
95 | methods viscolor importing visibility type i
96 | returning value(r_result) type string.
97 |
98 | methods bold importing base type string
99 | returning value(r_result) type string.
100 |
101 | methods italics importing base type string
102 | returning value(r_result) type string.
103 | methods underline importing base type string
104 | returning value(r_result) type string.
105 | methods add_table_cell importing table type ref to zcl_abap_graph_node_table
106 | desc type zcl_debug_obj_graph_factory=>ty_data_desc
107 | line type i
108 | value(compname) type string
109 | returning value(componentid) type string.
110 |
111 | ENDCLASS.
112 |
113 |
114 |
115 | CLASS ZCL_DEBUG_OBJ_GRAPH_FACTORY IMPLEMENTATION.
116 |
117 |
118 | method add_record_component.
119 | data: id type string,
120 | partid type string,
121 | color type string,
122 | compname type string,
123 | value type string.
124 |
125 | id = component-desc-name .
126 |
127 | if component-desc-haschildren = abap_true.
128 | partid = component-compname.
129 | value = get_value( component-desc ).
130 | else.
131 | partid = ''.
132 | value = component-value .
133 | endif.
134 | compname = bold( component-compname ).
135 |
136 | color = viscolor( component-visibility ).
137 | componentid = record->addcomponent(
138 | name = compname
139 | value = value
140 | escape = abap_false
141 | bgcolor = color
142 | partid = partid ).
143 |
144 | endmethod.
145 |
146 |
147 | method add_table_cell.
148 | data: partid type string,
149 | value type string,
150 | linkedid type string.
151 | log( |R{ desc-refname }_C{ compname }_L{ line } | ).
152 | if desc-refname <> ''.
153 | if compname = ''.
154 | partid = |l{ line }|.
155 | else.
156 | partid = |l{ line }c{ compname }|.
157 | endif.
158 | else.
159 | partid = ''.
160 | endif.
161 | if compname = ''.
162 | compname = c_dummy.
163 | endif.
164 |
165 | value = get_value( desc ).
166 |
167 | log( |R{ desc-refname }_C{ componentid }_V{ value } | ).
168 |
169 | componentid = table->setcell(
170 | columnid = compname
171 | row = line
172 | value = value
173 | escape = abap_false
174 | partid = partid ).
175 |
176 | if desc-refname <> '' and componentid <> '' .
177 | linkedid = get_or_create_node( desc-refname ).
178 | if linkedid <> ''.
179 | table->linkto( destination = linkedid source = componentid ).
180 | endif.
181 | endif.
182 |
183 | endmethod.
184 |
185 |
186 | method bold.
187 | if base <> ''.
188 | concatenate '' base '' into r_result.
189 | endif.
190 | endmethod.
191 |
192 |
193 | method create.
194 |
195 | create object r_result.
196 |
197 | r_result->max_tab_lines = i_max_tab_lines.
198 |
199 | endmethod.
200 |
201 |
202 | method create_graph.
203 | data: desc type zcl_debug_obj_graph_factory=>ty_data_desc.
204 |
205 | graph = zcl_abap_graph=>create( ).
206 | me->graph = graph.
207 |
208 | desc = get_data_desc( root ).
209 |
210 | if desc is initial.
211 | message 'Variable not found' type 'S'.
212 | else.
213 | create_node_new( desc ).
214 | endif.
215 |
216 | endmethod.
217 |
218 |
219 | method create_node_new.
220 |
221 | if desc-istable = abap_true.
222 | node = create_table_node( desc ).
223 | elseif desc-hascomponents = abap_true.
224 | node = create_record_node( desc ).
225 | else.
226 | node = create_simple_node( desc ).
227 | endif.
228 |
229 | endmethod.
230 |
231 |
232 | method create_record_node.
233 | data: value type string,
234 | id type string,
235 | linkedid type string,
236 | components type tt_component,
237 | record type ref to zcl_abap_graph_node_record,
238 | componentid type string,
239 | ex type ref to cx_root.
240 | field-symbols: like line of components.
241 |
242 | try.
243 | components = get_components( desc ).
244 |
245 | value = get_head_label( desc ).
246 | id = desc-name .
247 | node = record = zcl_abap_graph_node_record=>create( graph = graph id = id label = value escape = abap_false ).
248 | record->headerattr->set( name = 'bgcolor' value = c_headerbg ).
249 |
250 | loop at components assigning .
251 | componentid = add_record_component( record = record component = ).
252 |
253 | if componentid <> ''.
254 | linkedid = get_or_create_node( -desc-refname ).
255 | if linkedid <> ''.
256 | node->linkto( destination = linkedid source = componentid ).
257 | endif.
258 | endif.
259 |
260 | endloop.
261 | catch cx_root into ex.
262 | log( |create_record_node exception { ex->get_text( ) } | ).
263 | endtry.
264 | endmethod.
265 |
266 |
267 | method create_simple_node.
268 | data: value type string,
269 | id type string,
270 | linkedid type string.
271 |
272 | value = desc-valuetext.
273 | id = desc-name .
274 | node = zcl_abap_graph_node_simple=>create( graph = graph id = id label = value ).
275 |
276 | if desc-haschildren = abap_true.
277 | linkedid = get_or_create_node( desc-refname ).
278 | if linkedid <> ''.
279 | node->linkto( linkedid ).
280 | endif.
281 | endif.
282 |
283 | endmethod.
284 |
285 |
286 | method create_table_node.
287 | data: value type string,
288 | id type string,
289 | components type tt_component,
290 | tabdesc type ref to cl_tpda_script_tabledescr,
291 | table type ref to zcl_abap_graph_node_table,
292 | linename type string,
293 | line type i,
294 | linedesc type zcl_debug_obj_graph_factory=>ty_data_desc,
295 | ex type ref to cx_root.
296 | field-symbols: like line of components.
297 |
298 |
299 | try.
300 | tabdesc ?= desc-descr.
301 | id = desc-name.
302 | value = get_head_label( desc ).
303 | log( |table { id }__{ value }| ).
304 | node = table = zcl_abap_graph_node_table=>create( graph = graph
305 | id = id
306 | label = value
307 | escape = abap_false ).
308 | table->headerattr->set( name = 'bgcolor' value = c_headerbg ).
309 | table->titleattr->set( name = 'bgcolor' value = c_headerbg ).
310 |
311 | do tabdesc->linecnt( ) times.
312 | line = sy-index.
313 | log( | table line { line } | ).
314 | linename = |{ desc-name }[{ line }]|.
315 | linedesc = get_data_desc( linename ).
316 | if line = 1 or not components is initial.
317 | components = get_components( linedesc ).
318 | if line = 1.
319 | "header
320 | if components is initial.
321 | table->setcolumn( id = c_dummy ).
322 | else.
323 | loop at components assigning .
324 | value = escapevalue( -compname ).
325 | value = bold( value ).
326 | table->setcolumn( id = -compname name = value ).
327 | endloop.
328 | endif.
329 | endif.
330 | endif.
331 |
332 | if components is initial.
333 | add_table_cell( table = table line = line desc = linedesc compname = '' ).
334 | else.
335 | "actual components of a line
336 | loop at components assigning .
337 | add_table_cell( table = table line = line desc = -desc compname = -compname ).
338 | endloop.
339 | endif.
340 | enddo.
341 | catch cx_root into ex.
342 | log( |create_table_node exception { ex->get_text( ) } | ).
343 | endtry.
344 |
345 | endmethod.
346 |
347 |
348 | method decodetype.
349 | data: base type string,
350 | extra type string.
351 |
352 | td-local = abap_true.
353 | td-name = typename.
354 | find regex '^\\TYPE=(.+)' in typename submatches base.
355 | if sy-subrc = 0.
356 | if base(1) = '%'.
357 | case desc-metatype.
358 | when cl_tpda_control=>mt_tab.
359 | base = 'table'.
360 | when cl_tpda_control=>mt_struct.
361 | base = 'structure'.
362 | when cl_tpda_control=>mt_class.
363 | base = 'class'.
364 | when others.
365 | base = 'type'.
366 | endcase.
367 | concatenate 'local ' base '' into base respecting blanks.
368 | else.
369 | td-local = abap_false.
370 | endif.
371 | td-name = base.
372 | return.
373 | endif.
374 | find regex '^\\PROGRAM=[^\\]*\\CLASS=([^\\]+)' in typename submatches base.
375 | if sy-subrc = 0.
376 | td-name = base.
377 | return.
378 | endif.
379 | find regex '^\\PROGRAM=[^\\]*\\CLASS=([^\\]+)' in typename submatches base.
380 | if sy-subrc = 0.
381 | td-name = base.
382 | return.
383 | endif.
384 | find regex '^\\CLASS-POOL=([^\\]+)\\CLASS=([^\\]+)' in typename submatches base extra.
385 | if sy-subrc = 0.
386 | concatenate base extra into td-name separated by space.
387 | return.
388 | endif.
389 | endmethod.
390 |
391 |
392 | method decode_visibility.
393 | case acckind.
394 | when if_tpda_control=>ak_private.
395 | r_result = c_private.
396 | when if_tpda_control=>ak_protected.
397 | r_result = c_protected.
398 | endcase.
399 | endmethod.
400 |
401 |
402 | method escapevalue.
403 | escaped = cl_http_utility=>escape_html( original ).
404 | endmethod.
405 |
406 |
407 | method get_components.
408 | data: odesc type ref to cl_tpda_script_objectdescr,
409 | sdesc type ref to cl_tpda_script_structdescr,
410 | tdesc type ref to cl_tpda_script_tabledescr,
411 | objattributes type tpda_script_object_attribut_it,
412 | scomponents type tpda_script_struc_componentsit,
413 | refname type string,
414 | match_offset type i,
415 | ex type ref to cx_root,
416 | basename type string.
417 | field-symbols: like line of scomponents,
418 | like line of components,
419 | like line of objattributes.
420 | try.
421 |
422 | case desc-metatype.
423 | when cl_tpda_script_data_descr=>mt_object.
424 | odesc ?= desc-descr.
425 | objattributes = odesc->attributes( ).
426 | when cl_tpda_script_data_descr=>mt_struct."struct
427 | sdesc ?= desc-descr.
428 | sdesc->components( importing p_components_it = scomponents ).
429 | find regex '\*$' in desc-name match offset match_offset.
430 | if match_offset = 0.
431 | basename = desc-name.
432 | else.
433 | basename = desc-name(match_offset).
434 | endif.
435 | basename = desc-name.
436 | when cl_tpda_script_data_descr=>mt_tab.
437 | tdesc ?= desc-descr.
438 | if tdesc->linecnt( ) > 0.
439 | log( |get_components probable casting exception after this line | ).
440 | sdesc ?= tdesc->get_line_handle( 1 ).
441 | sdesc->components( importing p_components_it = scomponents ).
442 | concatenate desc-name '[1]' into basename.
443 | endif.
444 | endcase.
445 |
446 | loop at objattributes assigning .
447 | append initial line to components assigning .
448 | -compname = -name.
449 | concatenate desc-name '-' -name into refname.
450 | -desc = get_data_desc( refname ).
451 | -visibility = decode_visibility( -acckind ).
452 | -value = get_value( -desc ).
453 | endloop.
454 |
455 | loop at scomponents assigning .
456 | append initial line to components assigning .
457 | -compname = -compname.
458 | -visibility = c_public.
459 | concatenate basename '-' -compname into refname.
460 | -desc = get_data_desc( refname ).
461 | -value = get_value( -desc ).
462 | endloop.
463 |
464 | catch cx_root into ex.
465 | log( |get_components { ex->get_text( ) } | ).
466 | endtry.
467 | if desc-metatype = cl_tpda_script_data_descr=>mt_object.
468 | sort components by visibility compname ascending.
469 | endif.
470 | endmethod.
471 |
472 |
473 | method get_data_desc.
474 | data: elem type ref to cl_tpda_script_elemdescr,
475 | string type ref to cl_tpda_script_stringdescr,
476 | table type ref to cl_tpda_script_tabledescr,
477 | odesc type ref to cl_tpda_script_objectdescr,
478 | info type tpda_scr_quick_info,
479 | ex type ref to cx_root.
480 |
481 | field-symbols: type tpda_sys_symbdatref,
482 | type tpda_sys_symbobjref.
483 |
484 | desc-name = name.
485 |
486 | try.
487 | desc-descr = cl_tpda_script_data_descr=>factory( name ).
488 | info = cl_tpda_script_data_descr=>get_quick_info( name ).
489 | desc-metatype = info-metatype.
490 | case info-metatype.
491 | when cl_tpda_script_data_descr=>mt_string.
492 | string ?= desc-descr.
493 | desc-valuetext = string->value( ).
494 | desc-valuetext = cl_http_utility=>escape_html( desc-valuetext ).
495 | when cl_tpda_script_data_descr=>mt_simple.
496 | elem ?= desc-descr.
497 | desc-valuetext = elem->value( ).
498 | desc-valuetext = cl_http_utility=>escape_html( desc-valuetext ).
499 | when cl_tpda_script_data_descr=>mt_struct.
500 | " desc-valuetext = cl_http_utility=>escape_html( info-abstypename ).
501 | desc-typedesc = decodetype( typename = info-abstypename desc = desc ).
502 | desc-hascomponents = abap_true.
503 | desc-haschildren = abap_true.
504 | desc-refname = name.
505 | when cl_tpda_script_data_descr=>mt_tab.
506 | table ?= desc-descr.
507 | if table->linecnt( ) > 0.
508 | desc-haschildren = abap_true.
509 | desc-istable = abap_true.
510 | desc-valuetext = ''.
511 | desc-refname = name.
512 | else.
513 | desc-valuetext = ''.
514 | endif.
515 | desc-typedesc = decodetype( typename = info-abstypename desc = desc ).
516 | when cl_tpda_script_data_descr=>mt_datref.
517 | assign info-quickdata->* to .
518 | find regex '^\{[A-Z]:initial\}$' in -instancename ignoring case.
519 | desc-isreference = abap_true.
520 | if sy-subrc <> 0.
521 | desc-haschildren = abap_true.
522 | desc-refname = -instancename.
523 | desc-valuetext = ''.
524 | else.
525 | desc-valuetext = ''.
526 | endif.
527 | when cl_tpda_script_data_descr=>mt_object.
528 | desc-haschildren = abap_true.
529 | desc-hascomponents = abap_true.
530 | odesc ?= desc-descr.
531 | desc-valuetext = odesc->classname( ).
532 | desc-typedesc = decodetype( typename = desc-valuetext desc = desc ).
533 | when cl_tpda_script_data_descr=>mt_objref.
534 | assign info-quickdata->* to .
535 | if -instancename <> '{O:initial}'.
536 | desc-haschildren = abap_true.
537 | desc-refname = -instancename.
538 | desc-valuetext = ''.
539 | else.
540 | desc-valuetext = ''.
541 | endif.
542 | desc-isreference = abap_true.
543 | endcase.
544 | catch cx_root into ex.
545 | clear desc.
546 | log( |get_data_desc exception { ex->get_text( ) } | ).
547 | endtry.
548 |
549 | endmethod.
550 |
551 |
552 | method get_head_label.
553 | if desc-istable = abap_true
554 | or desc-hascomponents = abap_true
555 | or desc-isreference = abap_true.
556 | r_result = escapevalue( desc-typedesc-name ).
557 | if desc-typedesc-local = abap_true.
558 | r_result = italics( r_result ).
559 | endif.
560 | endif.
561 | if r_result is initial.
562 | r_result = escapevalue( desc-valuetext ).
563 | endif.
564 | endmethod.
565 |
566 |
567 | method get_node_id.
568 | id = name.
569 | endmethod.
570 |
571 |
572 | method get_or_create_node.
573 | data: desc type zcl_debug_obj_graph_factory=>ty_data_desc,
574 | node type ref to zif_abap_graph_node.
575 |
576 | node = graph->get_node( name ).
577 |
578 | if not node is bound.
579 | "look up cache
580 | desc = get_data_desc( name ).
581 | node = create_node_new( desc ).
582 | endif.
583 |
584 | if node is bound.
585 | nodeid = node->id.
586 | endif.
587 |
588 | endmethod.
589 |
590 |
591 | method get_value.
592 | if desc-istable = abap_true
593 | or desc-hascomponents = abap_true
594 | or desc-isreference = abap_true.
595 | r_result = escapevalue( desc-typedesc-name ).
596 | if desc-typedesc-local = abap_true.
597 | r_result = italics( r_result ).
598 | endif.
599 | r_result = underline( r_result ).
600 | if r_result is initial.
601 | r_result = escapevalue( desc-valuetext ).
602 | endif.
603 | endif.
604 |
605 | if r_result is initial.
606 | r_result = escapevalue( desc-valuetext ).
607 | endif.
608 |
609 | endmethod.
610 |
611 |
612 | method italics.
613 | if base <> ''.
614 | concatenate '' base '' into r_result.
615 | endif.
616 | endmethod.
617 |
618 |
619 | method log.
620 | logs = |{ logs }{ cl_abap_char_utilities=>cr_lf }{ entry }|.
621 | endmethod.
622 |
623 |
624 | method underline.
625 | if base <> ''.
626 | concatenate '' base '' into r_result.
627 | endif.
628 | endmethod.
629 |
630 |
631 | method viscolor.
632 |
633 | case visibility.
634 | when c_protected.
635 | r_result = c_protected.
636 | when c_private.
637 | r_result = c_privatebg.
638 | endcase.
639 |
640 | endmethod.
641 | ENDCLASS.
642 |
--------------------------------------------------------------------------------
/zcl_debug_obj_graph_factory.clas.locals_def.abap:
--------------------------------------------------------------------------------
1 | *"* use this source file for any type of declarations (class
2 | *"* definitions, interfaces or type declarations) you need for
3 | *"* components in the private section
4 | class bd definition inheriting from CL_TPDA_SCRIPT_DATA_DESCR.
5 | public section.
6 | class-methods:vname importing descr type ref to CL_TPDA_SCRIPT_DATA_DESCR
7 | returning value(varname) type string.
8 | endclass.
9 |
--------------------------------------------------------------------------------
/zcl_debug_obj_graph_factory.clas.locals_imp.abap:
--------------------------------------------------------------------------------
1 | *"* use this source file for the definition and implementation of
2 | *"* local helper classes, interface definitions and type
3 | *"* declarations
4 |
5 |
6 | class bd implementation.
7 |
8 | method vname.
9 | varname = descr->var_name.
10 | endmethod.
11 |
12 | endclass.
13 |
--------------------------------------------------------------------------------
/zcl_debug_obj_graph_factory.clas.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ZCL_DEBUG_OBJ_GRAPH_FACTORY
7 | 1
8 | E
9 | Graph object factory
10 | 2
11 | 1
12 | X
13 | X
14 | X
15 | X
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/zcl_debug_obj_to_graph.clas.abap:
--------------------------------------------------------------------------------
1 | ********************************************************************************
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2018 Marcello Urbani
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | ********************************************************************************
24 | class zcl_debug_obj_to_graph definition public final create public .
25 |
26 | public section.
27 |
28 | methods display_graph importing !name type string.
29 | methods popup returning value(varname) type string.
30 | protected section.
31 | private section.
32 |
33 | constants c_newline like cl_abap_char_utilities=>newline value cl_abap_char_utilities=>newline ##NO_TEXT.
34 |
35 | data uploadpath type string.
36 | data downloadpath type string.
37 |
38 |
39 | methods get_temp_file_url
40 | returning
41 | value(r_result) type string.
42 |
43 |
44 | endclass.
45 |
46 |
47 |
48 | class zcl_debug_obj_to_graph implementation.
49 |
50 | method display_graph.
51 | data: lx_root type ref to cx_root,
52 | factory type ref to zcl_debug_obj_graph_factory,
53 | graph type ref to zcl_abap_graph.
54 | try.
55 | if name is initial.
56 | return.
57 | endif.
58 | factory = zcl_debug_obj_graph_factory=>create( ).
59 | graph = factory->create_graph( name ).
60 | if graph is bound.
61 | zcl_abap_graph_utilities=>show_in_browser( graph = graph comments = factory->logs ).
62 | else.
63 | message 'Unknown variable'(006) type 'I'.
64 | endif.
65 |
66 | catch cx_tpda_varname.
67 | message 'Unknown variable'(006) type 'I'.
68 | catch cx_root into lx_root.
69 | message lx_root type 'I'.
70 | endtry.
71 |
72 | endmethod.
73 |
74 | method get_temp_file_url.
75 | data: separator type c,
76 | guid type guid_32.
77 |
78 | cl_gui_frontend_services=>get_file_separator(
79 | changing
80 | file_separator = separator
81 | exceptions
82 | others = 4 ).
83 | if sy-subrc = 0.
84 | "will not work with local variables...
85 | cl_gui_frontend_services=>get_upload_download_path(
86 | changing
87 | upload_path = uploadpath
88 | download_path = downloadpath
89 | exceptions
90 | others = 6 ).
91 | endif.
92 | if sy-subrc = 0.
93 | call function 'GUID_CREATE'
94 | importing
95 | ev_guid_32 = guid.
96 |
97 | if downloadpath is initial.
98 |
99 | concatenate guid '.html' into r_result.
100 |
101 | else.
102 |
103 | concatenate downloadpath separator guid '.html' into r_result.
104 |
105 | endif.
106 | endif.
107 |
108 | endmethod.
109 |
110 | method popup.
111 | data: ok type abap_bool.
112 |
113 | call function 'POPUP_GET_STRING'
114 | exporting
115 | label = 'Variable name'
116 | importing
117 | value = varname
118 | okay = ok.
119 |
120 | if ok = abap_false.
121 | clear varname.
122 | else.
123 | translate varname to upper case.
124 | endif.
125 |
126 | endmethod.
127 |
128 | endclass.
129 |
--------------------------------------------------------------------------------
/zcl_debug_obj_to_graph.clas.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ZCL_DEBUG_OBJ_TO_GRAPH
7 | 1
8 | E
9 | Convert abap object to graph
10 | 2
11 | 1
12 | X
13 | X
14 | X
15 | X
16 |
17 |
18 |
19 | ZCL_DEBUG_OBJ_TO_GRAPH
20 | C_NEWLINE
21 | E
22 | C_NEWLINE
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------