sasjs-lint について
sasjs-lintは、@sasjs/lintでSASコードを検査・整形する方法を説明するスキルリファレンスです。設定、ルール、フォーマッターの動作に加え、CLI、VS Code拡張機能、Server Studio、ライブラリAPIでの利用方法を解説します。
主な機能
- 01SASソースファイルの lint ルール
- 02プロジェクト単位・ファイル単位の設定
- 03重要度設定と診断の動作
- 04対応する自動修正フォーマッター
- 05CLI、VS Code、Server Studio、APIでの利用
活用シーン
- 01SASプロジェクトの.sasjslint設定
- 02lint警告の理解や調整
- 03エディターワークフローやCIへの検査・整形の導入
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sasjs/ skills --skill sasjs-lintインストール後、Claude Code で/sasjs-lintを入力して読み込まれたか確認します。
詳細
@sasjs/lint
@sasjs/lint は、SAS コード向けのリンティングおよびフォーマットエンジンです。SAS に依存しない TypeScript ライブラリで、.sas ファイルをテキストとして読み込みます。また、sasjs lint、SASjs VS Code 拡張機能の Problems パネル、SASjs Server Studio を支える単一のエンジンです。
このスキルでは、ルール、.sasjslint ファイル、フォーマッター、および実行方法を取り上げます。SAS 言語自体(sas を参照)や CLI のその他の機能(sasjs-cli を参照)は対象外です。
以下のルールとデフォルト設定は、@sasjs/cli 6.2.5 に同梱されている @sasjs/lint 4.5.0 に基づいて確認されています。このライブラリには随時ルールが追加されるため、古いバージョンを固定している環境では、すべてのルールが利用できるわけではありません。実行環境を参照してください。
使用する場面
.sasjslintファイルを作成または変更するときsasjs lintの実行で警告が表示され、その意味や抑制方法を確認するとき- CI パイプラインまたは git のコミット前フックにリンティングを追加するとき
- フォーマッターを実行するとき(
sasjs lint fix、保存時のフォーマット、formatText) - エディターでルールが適用される理由、または適用されない理由を説明するとき
実行環境
| 環境 | 実行方法 | 備考 |
|---|---|---|
| SASjs CLI | sasjs lint、sasjs lint find、sasjs lint fix、sasjs lint init | find がデフォルトのサブコマンドです。init は、デフォルト設定一式を含む .sasjslint をプロジェクトのルートに書き込みます |
VS Code 拡張機能(sasjs/sasjs-for-vscode、Open VSX で公開) | Problems パネル(ctrl+shift+M)、ドキュメントのフォーマット、保存時のフォーマット | 設定の優先順位:プロジェクトの .sasjslint > 設定 sasjs-for-vscode.lintConfig > ~/.sasjslint > デフォルト設定 |
| SASjs Server Studio | POST /SASjsApi/code/lint および POST /SASjsApi/code/format、本文 { code, filePath } | ルールは、SASjs Drive 上でファイルのフォルダーから Drive のルートまで上位にたどり、最も近い .sasjslint から取得されます。Drive のルートにある .sasjslint は初回起動時に配置され、ファイルツリーには /.sasjslint として表示されます |
| ライブラリ | lintText、lintFile、formatText、formatFile、およびフォルダー/プロジェクト向けの各バリエーション | 詳細は以下の API セクションを参照してください |
4 つの環境はすべて同じルールを呼び出します。CLI、拡張機能、サーバーはそれぞれ異なるバージョンの @sasjs/lint を固定しているため、ライブラリに追加されたルールは、その環境が依存関係を更新して初めて利用できるようになります。エディターでルールが適用されるはずだとユーザーに伝える前に、固定されているバージョンを確認してください。
設定の解決
設定を渡さない場合、ライブラリは次の順序で設定を解決します。
- プロジェクトルートの
.sasjslint(ライブラリはプロジェクトを見つけるために親ディレクトリをたどります) - ユーザーのホームディレクトリにある
.sasjslint DefaultLintConfiguration— 組み込みのデフォルト設定
設定が存在しない場合はデフォルト値が使われます。また、.sasjslint が存在しないプロジェクトにもデフォルト値が適用されます。DefaultLintConfiguration は @sasjs/lint/utils/getLintConfig からエクスポートされており、sasjs lint init が書き出す設定です。
.sasjslint ファイル
{
"noTrailingSpaces": true,
"maxLineLength": 100,
"noSingleAsteriskComments": true,
"severityLevel": {
"hasDoxygenHeader": "warn",
"noEncodedPasswords": "error"
}
}
ルールとデフォルト設定
2つのグループがあり、ルールをオフにする方法はどちらのグループに属するかによって異なります。
デフォルトでオン — false でオフ(注記がある場合を除く):
| 設定 | デフォルト | 重大度 | チェック内容 |
|---|---|---|---|
hasDoxygenHeader | true | WARNING | ファイルが /** の Doxygen ヘッダーで始まっていること |
hasMacroNameInMend | true | WARNING | %mend にマクロ名が付いていること |
hasMacroParentheses | true | WARNING | マクロが括弧付きで定義され、( の前にスペースがないこと |
noNestedMacros | true | WARNING | 別のマクロ内で %macro が定義されていないこと |
strictMacroDefinition | true | WARNING | パラメーター名にスペースがないこと(%macro m(my var);)、認識されないオプションがないこと(%macro m()/nonsense;) |
noUndeclaredMacros | true | WARNING | ファイルが呼び出すすべてのマクロが、そのファイルまたはヘッダーで宣言されていること |
noUnusedMacros | true | WARNING | <h4> SAS Macros </h4> 内のすべてのマクロが実際に呼び出されていること |
noNestedCommentsInHeader | true | WARNING | 開始 Doxygen ヘッダーに */ が含まれていないこと。SAS はこれをコメントの終わりと解釈するため、その後の内容は @param 行や使用例も含め、すべて SAS としてコンパイルされます |
noBannedStrings | true | WARNING | 行に設定済み文字列が含まれていないこと。デフォルトではログに見せかける語句 error 、error:、warning 、warning: が対象です。大文字と小文字を区別せず、コメントも対象です |
noTrailingSpaces | true | WARNING | 行末に空白がないこと |
noTabs | true | WARNING | タブ文字がないこと。別名:noTabIndentation(非推奨) |
noGremlins | true | WARNING | ゼロ幅文字など、標準外の文字がないこと |
indentationMultiple | 2 | WARNING | 行頭のスペースがこの数で割り切れること |
lowerCaseFileNames | true | WARNING | ファイル名が小文字であること(*nix ではオートコールに必要です) |
noSpacesInFileNames | true | WARNING | ファイル名にスペースが含まれていないこと |
noEncodedPasswords | true | ERROR | {sas00X} または {sasenc} でエンコードされたパスワードがないこと |
maxLineLength | 80 | WARNING | 行の長さ。0 でオフにします |
デフォルトでオフ — true でオン:
| 設定 | デフォルト | 重大度 | チェック内容 |
|---|---|---|---|
noSingleAsteriskComments | false | WARNING | * text; 形式のコメント文 |
noUnusedLibnames | false | WARNING | ファイルが割り当てているものの、使用していないライブラリ参照名 |
hasRequiredMacroOptions | false | WARNING | マクロに requiredMacroOptions のオプションが付いていること |
lineEndings | "off" | WARNING | 改行コードが lf または crlf に準拠していること |
補助設定(ルールではありません):
| 設定 | デフォルト | 目的 |
|---|---|---|
ignoreList | [] | スキップするパス。.gitignore 内のファイルもスキップされます |
allowedGremlins | [] | "0x0080" のような4桁の16進数文字列 |
defaultHeader | 下記を参照 | /** ヘッダーのないファイルに適用するヘッダーテンプレート |
severityLevel | {} | ルールごとの "warn" / "error" の上書き設定 |
maxHeaderLineLength | 80 | ヘッダー内の行の長さ制限 |
maxDataLineLength | 80 | datalines / cards / parmcards レコード内の行の長さ制限 |
requiredMacroOptions | [] | hasRequiredMacroOptions が必須とするオプション |
ignoredLibnames | [] | noUnusedLibnames が無視するライブラリ参照名 |
ignoredMacros | ["webout"] | noUndeclaredMacros が宣言済みとして扱うマクロ名。設定するとデフォルトを置き換えます — 下記を参照 |
bannedStrings | ["error ", "error:", "warning ", "warning:"] | noBannedStrings が報告する文字列。設定するとデフォルトを置き換えます — 下記を参照 |
重大度と終了コード
すべてのルールには、オフ、WARNING、ERROR の3つの状態があります。sasjs lint がゼロ以外の終了コードを返すのは、ERROR が報告された場合のみです。警告では終了コードは0のままなので、終了コードを基準とするフックやパイプラインでは、警告のみのファイルは通過します。デフォルトで ERROR に設定されているルールは noEncodedPasswords のみです。
severityLevel はルール名を指定して重大度を引き上げたり引き下げたりします。指定できる値は "warn" と "error" のみです。それ以外の値は警告なしで無視されます。
{
"severityLevel": {
"maxLineLength": "error",
"hasDoxygenHeader": "warn"
}
}
ファイルごとのオーバーライド
ファイルのルールは、Doxygen ヘッダー内の @sasjslint ブロックで調整します。
/**
@file
@brief Calls the settlement API
@sasjslint {"maxHeaderLineLength": 200, "noUndeclaredMacros": false}
<h4> SAS Macros </h4>
@li mf_trim.sas
**/
- スカラー値は置き換えられ、配列は追加されます(
allowedGremlins、requiredMacroOptions、ignoredLibnamesには、置き換えではなく項目が追加されます)。オブジェクトはキーごとにマージされます(severityLevel)。 - オーバーライドはフォーマッターにも適用されるため、
sasjs lint fixでも尊重されます。noUnusedMacrosを無効にしたファイルでは、無効にしなければヘッダーから削除される項目が保持されます。 - 読み取られるのはヘッダーだけで、タグの直後に
{が続く行だけが対象です。不正なブロックや閉じられていないブロックは、エラーにならず無視されます。 - ヘッダーの設定は、呼び出し元から渡された設定より優先されます。
- ヘッダーで使用できない設定は
ignoreListだけです。これはファイルが読み込まれる前に評価されます。 - フォーマッターが書き換える
<h4> SAS Macros </h4>セクションの外側にブロックを配置してください。
ignoredMacros と bannedStrings
どちらもリストで、プロジェクトレベルの値は組み込みのデフォルトを拡張するのではなく、置き換えます。ignoredMacros を明示すると、再度記載しない限り webout は除外されます。また、"bannedStrings": [] は何も報告しません。ファイルごとの @sasjslint ブロックでは逆に配列が追加されるため、ファイルはプロジェクトのリストに項目を追加でき、既存の項目を再記載する必要はありません。
ignoredMacros を読み取るのは noUndeclaredMacros だけです。noUnusedMacros には影響しないため、ヘッダーで宣言されているのに呼び出されていないマクロについては、逆の警告をこの方法で抑制できません。その項目を削除するか、そのファイルで該当ルールを無効にしてください。
ignoredMacros がある理由:プロバイダー経由で提供されるマクロ
リンターが読み取るのは1つのファイルと設定だけです。ビルドの残りの部分については何も把握しておらず、sasjs lint は sasjsconfig.json の情報を渡しません。そのため、コンパイル時に別の方法で利用可能になる場合でも、マクロを呼び出すファイル内で宣言する必要があります。
- serviceInit プログラム(ターゲット設定の
serviceInit。すべてのサービスにコンパイルされます)では、自身の<h4> SAS Macros </h4>内でマクロファイルを宣言します。サービス本体は宣言なしでこれらのマクロを呼び出せますが、呼び出しごとに警告が出ます。 sasjs testで同じ役割を担う testSetUp/testInit プログラム。- コンパイラー自体が挿入するもの。
%weboutは組み込みのケースであり、そのためweboutがデフォルトのリストに含まれています。
これらの場合は、プロジェクトの .sasjslint に記載するのが適切です。
{
"ignoredMacros": ["webout", "mpeinit", "mpeterm"]
}
注意点が2つあります。デフォルトのリストは置き換えられるため、webout を再記載してください。省くと、ストリーミングを行うすべてのサービスで %webout が報告されます。また、プロジェクト全体の項目は、マクロが本当に不足しているファイルでもチェックを抑制するため、呼び出す可能性のあるすべてのファイルにマクロが届く場合に限って記載してください。プロバイダーが一部のファイルだけを対象とする場合は、ファイル単位の @sasjslint {"ignoredMacros": [...]} のほうが適しています。
bannedStrings
デフォルトの4項目は、ログメッセージに見える単語です。これらを含むコメントや %put は SAS ログの検索結果に現れ、そうしたログを基にするログスキャナーでも検出されるため、文章にすぎない一致に紛れて本当の問題を見失いやすくなります。一致判定では大文字と小文字を区別せず、長い文字列から先に処理し、重複する範囲を二重に報告しません。また、次の2つは対象外です。
datalines/cards/parmcardsのレコード。ここではテキストはコードではなくデータです。@sasjslintブロックを含む行。これにより、ファイルは独自のオーバーライドで禁止文字列を設定できます。
文章の表現を変えてください。テキストをログにそのまま残す必要がある場合は、マクロ関数を使って単語を分割します。%put %str(WARN)ING: message は WARNING: message を出力し、リテラル文字列を保持しなくなります。Doxygen の @warning タグは文章ではなくコンテンツなので、そのファイルでは @sasjslint {"noBannedStrings": false} を指定してください。
フォーマッター
フォーマッターは、保存時に修正可能なルールを適用します。現在実装されている機能は次のとおりです。
%mendにマクロ名を追加する- ファイルに Doxygen ヘッダーがない場合、テンプレートを追加する
- ファイルで使用されているマクロを
<h4> SAS Macros </h4>に追加し、重複を削除して並べ替える - ファイルで使用されていないマクロをそのセクションから削除する
- 行末の空白を削除する
未実装の機能(次の機能を保証しないでください):タブをスペースに変換する、gremlin を削除する、行末を修正する、単一アスタリスクのコメントをブロックコメントに変換する。
defaultHeader では {lineEnding} を改行のプレースホルダーとして使用します。リテラルの \n は機能しません。
{
"defaultHeader": "/**{lineEnding} @file{lineEnding} @brief Our Company Brief{lineEnding}**/"
}
ライブラリ API
import { lintText, lintFile, formatText, formatFile, LintConfig, Severity } from '@sasjs/lint'
const diagnostics = await lintText(code, config) // config optional
const fixed = await formatText(code, config) // config optional
lintText(text, configuration?)、lintFile(path, configuration?)、lintFolder、lintProjectformatText(text, configuration?)、formatFile、formatFolder、formatProjectnew LintConfig(json)はプレーンオブジェクトから設定を構築し、config.override(json)はオーバーライドをマージした新しい設定を返しますDiagnosticはmessage、lineNumber、startColumnNumber、endColumnNumber、severityを保持しますSeverityはInfo(0)、Warning(1)、Error(2)です
呼び出し元がルールを把握している場合は、LintConfig を明示的に渡すことが重要です。ディスク上にパスのないバッファーをリントするサーバーやエディターは、作業ディレクトリの走査に依存できません。
落とし穴
- ルールによってオフの意味が異なります。 デフォルトで有効なルールは
falseでオフになります。maxLineLengthは0で、lineEndingsは"off"でオフになります。デフォルトで無効なルールはfalseを無視します(省略した場合と同じです)。有効にするにはtrueが必要です。設定を間違えると、ルールが「機能しない」最も一般的な原因になります。 maxLineLengthがオフの場合、maxHeaderLineLengthとmaxDataLineLengthは機能しません。これらはmaxLineLengthの適用範囲内にあるためです。実際に適用される上限は2つの値のうち大きい方なので、片方をmaxLineLengthより小さく設定しても、何も通知されず無視されます。ignoredMacrosとbannedStringsは、明示的なリストを指定するとデフォルトが置き換えられます。 デフォルト値が設定されるのは、設定項目が存在しない場合のみです。そのため、"ignoredMacros": ["mpeinit"]とするとweboutも無視されなくなり、"bannedStrings": []とするとデフォルト値に戻るのではなく、何も報告されなくなります。引き続き使いたいデフォルト値は、改めて記述してください。noUnusedMacrosとフォーマッターを併用すると、@liの依存関係が削除されます。 これらの項目はコンパイラーによって処理されるため、動的な%&name呼び出しや%includeされたプログラムなどを介して間接的にのみ参照されているマクロは宣言が削除され、ジョブのアセンブルに失敗する場合があります。そのような場合は、プロジェクトまたはファイルでこのルールをオフにしてください。- ヘッダーの項目は、ファイル内でマクロが呼び出されていなくてもビルドに不可欠な場合があるため、削除する前に確認してください。 コンパイラーは、別の宣言済みマクロ自身の
<h4>が要求するものもインライン展開します。そのため、項目がその依存関係と重複している場合(削除しても問題なく、生成されるプログラムは変わりません)もあれば、そのマクロがファイルに到達する唯一の経路である場合(削除するとビルドが壊れます)もあります。確認するには、コンパイルして生成物を grep します。編集前後にsasjs compileを実行し、続けてgrep -c "%macro <name>" sasjsbuild/services/<path>.sasを実行してください。 noUndeclaredMacrosはSASAUTOSを認識しません。 SAS に付属するマクロは常に宣言済みとして扱われます(一覧は@sasjs/sas-languageから生成されます)が、SASAUTOSを介して使用可能になったマクロはリンターから認識されず、報告されます。ヘッダーで宣言するか、このルールをオフにしてください。noBannedStringsは、コード内だけでなくコメントやヘッダーの文章に含まれる単語も報告します。 ファイルに問題がないように見えても検出されることがあり、[line, column]は単語そのものの位置を示します。3つの対処方法についてはbannedStringsを参照してください。表現を変える、%str(WARN)INGを使う、または doxygen タグにファイル単位の上書きを設定する方法があります。noUnusedLibnamesは意図的に幅広く判定します。 libref は、LIBNAME文の外ならどこに出現しても使用中として扱われます。pathname("outData", "L")のような二重引用符付き文字列内も含まれます。このルールはファイルだけでは完全なジョブにならないため、デフォルトではオフであり、フォーマッターによる修正機能もありません。- 空の
.sasjslintは.sasjslintが存在しない場合と同じではありません。 ただし、これはデフォルト値が以前は条件付きで適用されていた設定に限ります。4.0.0 以降、maxLineLengthまたはhasMacroNameInMendが設定されていない場合は、ドキュメントに記載されたデフォルト値(それぞれ 80 とtrue)が適用されます。そのため、これらの項目を省略してルールを無効にしていたプロジェクトでは、"maxLineLength": 0または"hasMacroNameInMend": falseを設定する必要があります。 allowedGremlinsの項目は数値ではなく文字列です。"0x0080"のように、16進数4桁で指定します。- CLI の出力は罫線文字で描画された表です。 ターミナルでの使用を想定しているため、境界線の文字が問題になる可能性を考慮せずに、プレーンテキストや ASCII のみの文書に貼り付けないでください。
- サブコマンドを指定せずに
sasjs lintを実行すると、sasjs lint findとして動作し、プロジェクト内のすべての.sasファイルを lint します。
検証
- ルールが適用されることを確認します。.sas ファイルに該当する構文を記述し、
terminal(command="npx sasjs lint")を実行します。検出されると、メッセージと[line, column]の位置を含む行が表示されます。行が表示されない場合は、ルールが無効になっているか、その構文が除外されています(まず設定を確認し、次にルールの除外設定を確認してください)。 - 設定の変更が反映されたことを確認します。.sasjslint を編集する前と後に
npx sasjs lintを実行し、表示される行を比較します。デフォルトで無効になっているルールを有効にするには、falseではなくtrueを指定する必要があります。 - フォーマッターの効果を確認します。
npx sasjs lint fixを実行し、差分を確認します。書き換えられるのは<h4> SAS Macros </h4>セクションと%mendの行です。 - ファイルごとのオーバーライドを確認します。
@sasjslintブロックを追加してsasjs lintを実行し、そのファイルでは無効にしたルールが報告されなくなり、隣接するファイルでは引き続き報告されることを確認します。 - 禁止文字列を確認します。ファイルに
%put WARNING: test;を記述してsasjs lintを実行すると、その位置に行が表示されます。これを%put %str(WARN)ING: test;に書き換えると行が表示されなくなり、ログには引き続きWARNING: testと表示されます。 ignoredMacrosを確認します。宣言されていないマクロを呼び出すファイルを lint し、その名前をプロジェクトの.sasjslintに追加すると、行が表示されなくなります。次に、同じリストからweboutを削除し、これを呼び出すサービスで%weboutが報告されることを確認します。このリストはデフォルトを拡張するのではなく、置き換えます。