关于 sasjs-core
@sasjs/core 是面向 SAS 应用开发者的 MIT 许可 SAS 宏库,适用于 SAS 9、Viya 和 SASjs server。本技能提供代码规范、测试和构建方面的静态参考,不会执行代码或访问外部系统。
主要功能
- 01SAS 宏编码规范
- 02目录和宏前缀约定
- 03安全中止处理指导
- 04宏测试与作用域检查
- 05Lint 和生成文件规则
适用场景
- 01添加 SAS 宏时遵循代码约定
- 02测试宏是否泄漏变量作用域
- 03按 lint 和构建规则检查变更
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sasjs/ skills --skill sasjs-core安装后在 Claude Code 中输入/sasjs-core确认已加载。
详细介绍
@sasjs/core - SAS 宏库
@sasjs/core 是一个采用 MIT 许可的库,包含适用于 SAS 应用开发的生产级 SAS 宏,可在 SAS 9(meta)、Viya 和 SASjs server 上移植使用。
编码规范(必须遵守)
- 每个文件只包含一个宏;文件名必须与宏名一致(小写,不含空格)
- 宏定义必须使用括号:
%macro x();,不能写成%macro x; - 宏调用末尾不得加分号:
%my_macro(),不能写成%my_macro(); - 所有宏变量都必须声明为
%local,以防止作用域泄漏 - 赋值 fileref 时始终使用
mf_getuniquefileref,赋值 libref 时始终使用mf_getuniquelibref(绝不硬编码或手动创建唯一引用) - 缩进使用 2 个空格,不使用制表符,不留尾随空格,不使用不可见字符;行长最多为 300 字符(硬性 lint 限制),但尽可能将行长控制在 80 字符以内
- 每个文件都必须包含 Doxygen 头部:
/**
@file
@brief One-line description of the macro
<h4> SAS Macros </h4>
@li mf_othermacro.sas
@param [in] paramname Description
@param [out] outparam Description
<h4> Related Macros </h4>
@li mp_related.sas
@version 9.4
@author Your Name
**/
文件夹/前缀约定
| 文件夹 | 前缀 | 平台 |
|---|---|---|
base/ | mf_(函数式)、mp_(过程式) | 所有平台 |
meta/ | mm_ | SAS 9 元数据 |
metax/ | mmx_ | SAS 9 元数据(依赖 OS 命令) |
viya/ | mv_ | Viya |
server/ | ms_ | SASjs server |
xplatform/ | mx_ | 运行时平台检测 |
fcmp/、lua/、ddl/ | - | PROC FCMP 函数、LUA 封装、DDL |
当宏返回的值可用于表达式时,使用 mf_ 宏;对于生成代码/语句的过程式宏,使用 mp_。
跨套件规则:mp_ 宏绝不能引用 mx_ 宏。平台分发(SAS 9/Viya/SASjs server)应放在 mx_ 套件中,由其按平台调用 ms_/mv_/PROC STP。如果某个 mp_ 宏看起来需要平台专属行为,那么该宏本身应放在 xplatform/ 中,作为 mx_ 宏。
优先复用,再编写
编写新宏之前,请先检查库中是否已有可用宏——常见工具已经存在,例如 mp_abort(已弃用的 mf_abort 为保持向后兼容而保留;新代码中不要使用它)、mf_existds、mf_existvar、mf_existfileref、mf_getuser、mp_jsonout(将 SAS 数据集转换为 JSON,输出到 _webout)、mp_ds2ddl、mp_hashdataset。meta/、viya/、server/ 下有平台专用变体,由 CLI 在编译时选择。
安全地中止
绝不要在 %if/%else 代码块中调用 %mp_abort——作为过程式宏,宏处理器可能会在中止生效前继续执行其中的语句。请改用 iftrue= 条件参数:
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program
,msg=%str(Something went wrong)
)
循环中也一样。在 %do %while 或 %do %to 循环体内调用 %mp_abort 可能导致循环继续运行:中止会取消当前步骤,而宏处理器随后会继续下一次迭代;如果循环正在等待一个永远不会出现的进度,那么中止本身就会再次触发,导致任务不断运行而不是失败。设置一个标志,退出循环本身,然后在 %end 之后中止:
%let stuck=0;
%do %while (&left>0);
/* ...work that may make no progress... */
%if &nready=0 %then %do;
%let stuck=1;
%let left=0; /* the loop condition, so it cannot re-enter */
%end;
%end;
%mp_abort(iftrue= (&stuck=1)
,mac=&sysmacroname
,msg=%str(No progress could be made)
)
经验法则:中止应放在结构末尾,绝不要放在结构内部——%mp_abort 是向步骤发出的请求,不是从宏中执行的 return。另一种相关情况是:在 %if <count> >0 %then %do ... %end 中包裹验证中止,并在其中设置 iftrue=1;应改为在调用时将计数传给 iftrue=,这样中止就不依赖外围代码块。
从 %include 代码块内部调用 %mp_abort 时,SAS 无法正常退出(例如退出到 _webout)。请在 include 之后(宏包装之外)调用 %mp_abort(mode=INCLUDE)——它会检查 work.mp_abort_errds 中的中止状态:
%mp_abort(mode=INCLUDE)
注意:宏内的 %include 应使用 %mp_include() 执行,以设置 _SYSINCLUDEFILEDEVICE 指示器,并将中止数据集(work.mp_abort_errds)传回调用程序。
测试宏(强制约定)
- 始终在待测宏外使用
%mp_assertscope,以捕获作用域泄漏(宏变量必须保持为%local):
%mp_assertscope(SNAPSHOT)
%mx_foo(args)
%mp_assertscope(COMPARE,
desc=Test 1: mx_foo does not leak scope,
outds=work.test_results
)
- 断言通过
%mp_assert(iftrue=(...), desc=..., outds=work.test_results)写入work.test_results。
Lint 和构建
- 每次更改后都运行
sasjs lint;通过之前不要认为工作已完成 - 绝不要提升
package.json中的版本(由 semantic-release 处理) - 不要手动编辑生成的文件:
all.sas、mc_*.sas、lua/包装器和sasjsbuild/输出均由 CI 构建生成 - Markdown 文件:绝不要强制换行;每行写一个段落
限制
此技能是 @sasjs/core 宏库的静态参考资料,提供编码标准、前缀约定和测试指导。它不会执行 SAS 代码、运行 shell 命令、访问文件系统、连接数据库或发起网络请求。所有代码示例仅供参考,必须由用户提交到 SAS 会话中执行。