ActionScript3.0でファイル名、行番号を取得

__FILE__と__LINE__

ActionScript3.0でソースコードのファイル名と行番号を表示したいと思ったので調べてみた。C言語で言う__FILE__と__LINE__を使いたいだけ。

なんか見つからない

あるぇー?おかしいな。余裕ですぐ見つかる気がしたのに。検索の仕方が悪かったかな。それとも、用意されてないということは、使う必要がないということかな?

諦めて回避策

考えても仕方がないので、自力で書くことにした。

getStackTrace

なんか意図的にスタックトレースが取れるみたい。*1
ただし、DebugバージョンのFlashPlayer限定。つまり、デバッグ目的以外には使えませんよ。と。

trace(new Error().getStackTrace());

これの出力って例えばこうなってる。

Error
	at test::test()[C:\Projects\AS3\ActionScriptTest\test\test\as:17]
	at ActionScriptTest()[C:\Projects\AS3\ActionScriptTest\ActionScriptTest.as:9]

0行目はエラーの名前とか。
1行目にErrorをnewした関数の情報。(at メソッド名[ファイル名:行番号])
2行目にその関数を呼び出した関数の情報。
3行目にさらにその関数を…と続く。
で、こいつを分解すればファイル名、メソッド名、行番号がとれる。
正規表現とか使ってこんな感じ。

// エラーを作成
var er:Error = new Error;

// スタックトレースを取得
var st:String = er.getStackTrace();

// 改行コードで分割
var sts:Array = st.split("\n");

// 2番目の行(3行目)を取得(呼び出し元)
var cl:String = sts[2];

// 行番号を取得するパターンを作成
var rg:RegExp = /at .+\[.+[\.|\\]as\:(\d+)\]/;

// 作成したパターンをマッチ
var mc:Array = cl.match(rg);

// 1番目のグループの値を取得
var mcl:String = mc[1];

// intにキャスト
var line:int = int(mcl);

// 行番号を返す
return line;

長ったらしいのでワンライナーにして、クラス化。

package lib
{
  /// ここ!クラス
  public class Hear
  {
    /// ファイル名
    static public function file(): String 
    {
      return new Error().getStackTrace().split("\n")[2].match( /at .+\[(.+?[\.|\\]as)\:\d+\]/)[1].replace(/([\.|\\]as$)/, ".as");
    }
    /// 短い(パスを含まない)ファイル名
    static public function sfile(): String 
    {
      return new Error().getStackTrace().split("\n")[2].match( /at .+\[(?:.+\\)(.+?[\.|\\]as)\:\d+\]/)[1].replace(/([\.|\\]as$)/, ".as");
    }
    /// メソッド名
    static public function method(): String 
    {
      return String(new Error().getStackTrace().split("\n")[2].match( /at (.+)\[.+[\.|\\]as\:\d+\]/)[1]).replace("/", ".");
    }
    /// 行番号
    static public function line(): int 
    {
      return int(new Error().getStackTrace().split("\n")[2].match( /at .+\[.+[\.|\\]as\:(\d+)\]/)[1]);
    }
  }
}

使うときはこうする。

package hoge
{
  import lib.Hear;
  public class foo
  {
    public function bar(): void
    {
      trace(lib.Hear.sfile() + "っていうファイルの" + lib.Hear.method() + "っていうメソッド("  +  lib.Hear.line() + "行目)で呼ばれたよ!");
    }
  }
}

表示はこんな感じ。

foo.asっていうファイルのhoge::foo.bar()っていうメソッド(8行目)で呼ばれたよ!

うーん。車輪の再発明のにおいがプンプンする。もっとスマートにできないものかな。