完整源代码见文末。
如今像 Visual Studio Code,Eclipse,Sublime Text,甚至 Chrome 这些编程 IDE,代码编辑器和开发辅助工具,通过 Extension & Plugin 的方式,来对其增添额外功能,仿佛已经成为编程工具圈里的标配了。
和这些后辈们相比,SAPGUI 算是爷爷级的存在了。
其实 SAPGUI 里的 ABAP 代码编辑器,比如 SE24,SE37,SE38 和 SE80,UI 和逻辑均由 ABAP 编写。因此理论上来说,一个 ABAP 开发者,如果觉得这些事务码某些方面的功能有所欠缺,大不了自己动手创建增强就行了。
只不过 SE80 等事务码的内部设计和逻辑,无论国内还是国外的技术博客,讲这一块的资料都很稀缺,所以很多想自己动手的朋友,也不知道从哪里入手。
本文就从 SE80 等 ABAP 代码编辑器的语法检查功能,如何去定制化作为例子,介绍 SAPGUI 环境下开发工具增强的实现步骤。
在 SAP 社区上已经有一些博客,介绍了如何在 ABAP Code Inspector 或 ATC Check 中,实现自定义的语法检查:
https://blogs.sap.com/2006/11/02/code-inspector-how-to-create...
在 SAPGUI 代码编辑器里,需要点击多次鼠标才能触发这些自定义实现的检查逻辑。
我这个人比较懒,能点一次鼠标或键盘就能完成的操作,我绝不想点两次。本文介绍的自定义语法检查逻辑,通过 SAPGUI 快捷键 Ctrl+F2 就能直接触发。
比如打开一个 ABAP 类的某个方法,点击语法检查图标,或按快捷键 Ctrl+F2:
这会触发我实现的自定义语法检查,具体逻辑是:
如果当前方法的总行数超过了硬编码的阈值,比如说 100,自定义语法检查的实现,就会在 Class Builder 中显示 Warning 消息,如下图所示:
对于仅仅使用 SAPGUI 来完成业务操作的用户来说,可能会认为在 SAPGUI 中的操作,比如在 Class Builder 类中双击一个方法,看到自己想要查看的内容,是一件顺理成章的事情。然而这些工具本身,底层的处理逻辑的实现复杂度,远远超出普通人的想象。
比如我在 SE80 里打开一个 ABAP 报表,双击某个 subroutine,在右边看到其源代码:
这个操作背后的处理流程如下图所示:
ABAP Workbench 中由用户发起的每一个操作,都被类 CL_WB_REQUEST 的一个实例封装,这个实例中包含了有关给定操作的所有详细信息,例如被点击对象的对象名称和对象类型(类方法,透明表或任何其他 ABAP 仓库对象),以及操作类型(增删改,查看等等)。
不同的请求操作类型由不同的 Handler Classes 来服求,这些类在配置表 WBREGISTRY 中统一维护。这个配置表的内容由类 CL_WB_REGISTRY 暴露。
类 CL_WB_MANAGER 作为一个中介,通过 CL_WB_REQUEST 的实例,以统一的方式与这些工具进行通信。
在有的 ABAP 代码编辑器的操作场景下,用户进行某种操作后,出于操作复杂性的因素,无法仅仅通过查看配置表 WBREGISTRY 来简单地确定对应的处理器类。在这种情况下,可以通过实现接口 IF_WB_DECISION_CLASS,来编写如何动态决定出需要指派哪一个 Handler Class 去响应用户发起的请求。
下面是对 ABAP 类方法的代码行数这一自定义语法检查的详细实现步骤。
- 通过继承标准类 CL_WB_CLEDITOR 的方式来创建一个新类 ZCL_WB_CLEDITOR. 这个新类的完整的源代码,可以通过阅读原文获得。
主要逻辑在方法 CHECK_METHOD_SOURCE 的重定义中实现。首先完成超类中的标准检查逻辑,如果发现语法错误,将它们显示给最终用户;否则在第 14 行执行自定义语法检查,也就是进入我编写的 custom_syntax_check 方法里。
custom_syntax_check 方法的实现逻辑很简单,读取当前被检查的 ABAP 方法的源代码到内表变量中,计算该内表的行数,如果大于 100,就抛出语法警告消息。
详细代码,大家请点击文末的阅读原文获得。
大家可能会问,我咋知道为什么要继承 CL_WB_CLEDITOR 这个类?好吧,我只是从单步调试中知道,当点击语法检查的图标,或使用快捷键 Ctrl+F2 时,会调用这个类:
- 在标准 ABAP 类 CL_OO_METHOD_REQ_DISPATCHER 的方法 GET_TOOL_FOR_REQUEST上创建一个新的 Post-Exit:
这个 Post-Exit 的实现很简单,返回我们在第一步扩展自标准类,并实现了自己自定义语法检查的子类 ZCL_WB_CLEDITOR.
在 Post-Exit 实现里,返回我们自定义的 ZCL_WB_CLEDITOR.
这样每当 Ctrl+F2 触发 ABAP 类的语法检查之后,我们自己编写的 ZCL_WB_CLEDITOR, 就会被 ABAP Editor 的处理框架调度并执行。
至此这个简单的 SAPGUI 环境下的 ABAP 语法检查的自定义增强需求就实现了。本文给出了扩展 SAPGUI 里标准功能的一些思路,大家在实际工作中可以灵活运用,来调整 SAPGUI 里一些标准事务码的行为,使其符合自己定制化的需求。
完整源代码
class ZCL_WB_CLEDITOR definition
public
inheriting from CL_WB_CLEDITOR
final
create public .
public section.
methods CHECK_METHOD_SOURCE
redefinition .
protected section.
private section.
methods CUSTOM_SYNTAX_CHECK
changing
!CHECK_LIST_OBJECT type ref to CL_WB_CHECKLIST .
ENDCLASS.
CLASS ZCL_WB_CLEDITOR IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_WB_CLEDITOR->CHECK_METHOD_SOURCE
* +-------------------------------------------------------------------------------------------------+
* | [--->] ALL_ERRORS TYPE CHAR1 (default =SPACE)
* | [<---] CHECK_LIST_OBJECT TYPE REF TO CL_WB_CHECKLIST
* | [<---] NAVIGATION_REQUEST TYPE REF TO CL_WB_REQUEST
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD check_method_source.
CALL METHOD super->check_method_source
EXPORTING
all_errors = all_errors
IMPORTING
check_list_object = check_list_object
navigation_request = navigation_request.
CHECK sy-uname = 'WANGJER'.
CHECK check_list_object IS INITIAL.
custom_syntax_check( CHANGING check_list_object = check_list_object ).
ENDMETHOD.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_WB_CLEDITOR->CUSTOM_SYNTAX_CHECK
* +-------------------------------------------------------------------------------------------------+
* | [<-->] CHECK_LIST_OBJECT TYPE REF TO CL_WB_CHECKLIST
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD custom_syntax_check.
CONSTANTS: cv_threshold TYPE int4 VALUE 100.
DATA: lt_source TYPE seop_source,
lt_text TYPE rsfb_source.
CALL FUNCTION 'SEO_METHOD_GET_SOURCE'
EXPORTING
mtdkey = mtdkey
state = 'A'
IMPORTING
source = lt_source.
IF lines( lt_source ) > cv_threshold.
check_list_object = NEW #( ).
APPEND `This warning message is raised by Jerry's custom syntax check` TO lt_text.
APPEND | method: { mtdkey-cpdname } has totally { lines( lt_source ) } lines of source code, please refact it to ensure | TO lt_text.
APPEND | no more than { cv_threshold } lines in a single method. | TO lt_text.
check_list_object->add_error_message( p_message_text = lt_text p_message_type = 'W' ).
ENDIF.
ENDMETHOD.
ENDCLASS.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。