見出し画像

#113 行番号をログに残すには?

C 言語でのプログラムの場合、__LINE__ とプログラム中に記述しておくと、コンパイルしたときにその部分がプログラムの行番号に置き換えられます。
このマクロを利用することで、デバッグ表示をするときにプログラムの何行目で表示させているのかをわかりやすくできます。

これを GAS でも実現しようとしてみました。

作成したプログラム

そして出来上がったのが、↓ のプログラム。

"use strict";           // 変数の宣言を強要する

function myFunction() {
  console.log('(1) LINE : ' + getCurrentLineNumber(new Error()) + '行目');

  console.log('(2) LINE : ' + getCurrentLineNumber(new Error()) + '行目');

  let error = new Error();
  console.log(error.stack);
}

function getCurrentLineNumber(error) {
  var stack = error.stack;
  var lineNumber = stack.split('\n')[1].split(':').reverse()[1];
  return lineNumber;
}
スクリプトエディタでの表示

12行目からの getCurrentLineNumber が行番号を取得するための関数で、myFunction は、実際に動作させるために作ってみたものです。

このプログラムを実行した結果が、↓ のような感じ。プログラムの 4行目・6行目の console.log で行番号を出力できています。

プログラムの実行結果

4行目・6行目のように、

getCurrentLineNumber(new Error())

と既述することで、行番号が得られます。それを、console.log などで表示すれば、目的は達成できます。😘

解説

このプログラムでは、GAS のベースになっている JavaScript の Error オブジェクトの stack プロパティを解析することで実現しています。

この stack プロパティは、標準化されたものではないので、今後の仕様変更などによって使えなくなる可能性があるものです。↑ のページでは
「標準外の Mozilla プロパティ」と説明されていますが、GAS でも利用できています。

具体的には、Error オブジェクトを生成すると、stack プロパティには ↓ のような文字列が設定されます。ここから目的の行番号を切り出します。

Error
    at myFunction (コード:8:15)
    at __GS_INTERNAL_top_function_call__.gs:1:8

関数 getCurrentLineNumber でポイントとなるのは、↓ の 1行です。

 var lineNumber = stack.split('\n')[1].split(':').reverse()[1];
  • stack.split('\n')[1]
    → 改行('\n')で文字列(stack プロパティ)を配列に分割し、その 2番目(配列は 0 から始まるので、2番目は [1])を指定する。これで、2行目が選択されたことになる。

  • .split(':')
    → 前項で選択した 2行目を、コロン(':')で配列に分割する。ここまでで配列には、以下のように格納される。

    1. at myFunction (コード

    2. 8

    3. 15)

  • .reverse()[1];
    → 配列の要素を .reverse() によって逆順にする。その 2番目の要素(言い換えれば、前項の後ろから 2番目の要素)を選択する。
    結果として 8 が lineNumber に設定される。

プログラムの動作は、このような感じです。冒頭のプログラムの 12行目からの 5行ばかりのプログラムによって、4行目や 6行目のように記述しておくことで、プログラムの行番号をログに記録できるようになります。

このようなテクニックが有用だと感じる人にとっては、とても便利なものなのでしょうが、理解できない人にとっては「何それ、おいしいの?」といった感じだと思います。このテクニックが必要な人に届きますように…😅

この記事が気に入ったらサポートをしてみませんか?