MXMLコンパイラ。 パート2.非文字列パラメーター初期化子

こんにちは、Habr!



前の記事で、Flexコンパイラの内部(MXMLの観点から)で教育プログラムを実行し、コンストラクターパラメーターを必要とするMXMLのクラスを操作する問題を取り除く方法について説明しました。 次に、バインドメカニズムを使用せずにパラメーターをカスタム値(定数など)に設定するという問題のもう一方の側面を分析します(ただし、非常によく似ています)。





はじめに

この記事が私が言ったより遅く出たという事実を事前に謝罪したい-私が雇われた記事の文字通りまさにその翌日、そして単に時間がない:)今、すべてが解決され、私は一連の記事を続ける準備ができている。



Flexを何らかの方法で使用した人は誰でも、次のようなものを思いついたと思います。

<TextField xmlns="flash.text.*" autoSize="{TextFieldAutoSize.CENTER}" />
      
      





mxmlcが生成するコードを見ると、次のようになります。

 private function _MyOwnFlexFrameworkTest_TextField1_i() : flash.text.TextField { var temp : flash.text.TextField = new flash.text.TextField(); _MyOwnFlexFrameworkTest_TextField1 = temp; mx.binding.BindingManager.executeBindings(this, "_MyOwnFlexFrameworkTest_TextField1", _MyOwnFlexFrameworkTest_TextField1); return temp; } // binding mgmt private function _MyOwnFlexFrameworkTest_bindingsSetup():Array { var result:Array = []; result[0] = new mx.binding.Binding(this, function():String { var result:* = (TextFieldAutoSize.CENTER); return (result == undefined ? null : String(result)); }, null, "_MyOwnFlexFrameworkTest_TextField1.autoSize" ); return result; }
      
      





プロパティを定数として指定するという些細なタスクのためのコードはたくさんありませんか?それは定義によって変わりませんか?



やりましょう!



私たちの目標は、民間のIDEでオートコンプリートをサポートするだけでなく、Flexプログラマーに視覚的になじみやすい下位互換性のある変更を加えることです。 上記のすべての要件を考慮すると、ソリューションは次のようになります。

 <TextField xmlns="flash.text.*" autoSize="${TextFieldAutoSize.CENTER}" />
      
      





ドル記号を使用するというアイデアはANTスクリプトに由来し、便利で明確であり、すでにフラッシャーの半分には馴染みがあります。



率直に言って、java.flex2.compiler.mxml.langパッケージ内のすべてのクラスを検索することからプロセスを開始しました(その理由は、ループの最初の記事を参照してください。))文字列 "@ {"のエントリを探します。 いわゆる双方向バインディングが始まるのは彼女であり、実装はそれらに基づいている可能性があります。 そして、私は幸運になりました! parseBindingExpressionメソッドは、 java.flex2.compiler.mxml.lang.TextParserですぐに検出されました



BindingExpression型のオブジェクトは、Binding式を示すために使用されるため、類推により、その隣に(パッケージflex2.compiler.mxml.repで)ExactValueExpressionクラスを作成します。

 package flex2.compiler.mxml.rep; public class ExactValueExpression { /** The source expression for this value */ private String exactValue; public ExactValueExpression(String exactValueExpression) { this.exactValue = exactValueExpression; } public String getValueExpression() { return exactValue; } }
      
      





これを独自のクラスメソッドjava.flex2.compiler.mxml.lang.TextParserで使用し、 parseExactValueExpressionと呼ぶことにしました。

 /** * @param s the string to be parsed * @return ExactValueExpression or null */ protected ExactValueExpression parseExactValueExpression(String s) { int dollarIdx; int openBraceIdx = -1; dollarIdx = StringUtils.findNextUnescaped('$', 0, s); if (dollarIdx == -1) { // String doesn't start with "$" return null; } openBraceIdx = StringUtils.findNextUnescaped('{', dollarIdx + 1, s); if (openBraceIdx != dollarIdx + 1) { // open bracet not in place return null; } int closeBraceIdx = StringUtils.findClosingToken('{', '}', s, openBraceIdx); if (closeBraceIdx == -1) { return null; } String contents = s.substring(openBraceIdx + 1, closeBraceIdx); if (contents.length() == 0) { // Convert ${} to null contents = "null"; } //Don't include the braces (or parens since they will just get stripped). return new ExactValueExpression( contents ); }
      
      





parseBindingExpressionを呼び出す前にこれを呼び出します。

 protected Object parse(String text, Type type, Type arrayElementType, int flags) { if (!inCDATA(flags)) { ExactValueExpression exactValueExpression = parseExactValueExpression(text); if(exactValueExpression != null) { return exactValueExpression; } // binding? if (!ignoreBinding(flags)) { BindingExpression result = parseBindingExpression(text); if (result != null) { return result; } else { text = cleanupBindingEscapes(text); } }
      
      







これで、デザインが正しく解析され、処理するだけになりました。 前の記事ですでにおなじみのjava.flex2.compiler.mxml.rep.init.ValueInitializer 、formatExprメソッドに進みます。 3行追加します。

 if(value instanceof ExactValueExpression) { return ((ExactValueExpression) value).getValueExpression(); }
      
      





antコンパイラコマンドを使用してプロジェクトをアセンブルし、 BUILD SUCCESSFULを待ちます(そのような結果が得られなかった場合は、最初からすべての手順を確認してください)。



結果



ドル記号を追加して元の例を変更しましょう。

 <TextField xmlns="flash.text.*" autoSize="${TextFieldAutoSize.CENTER}" />
      
      





すべてを正しく行った場合、結果は次のようになります。

 private function _MyOwnFlexFrameworkTest_TextField1_i() : flash.text.TextField { var temp : flash.text.TextField = new flash.text.TextField(); temp.autoSize = TextFieldAutoSize.CENTER; _MyOwnFlexFrameworkTest_TextField1 = temp; mx.binding.BindingManager.executeBindings(this, "_MyOwnFlexFrameworkTest_TextField1", _MyOwnFlexFrameworkTest_TextField1); return temp; }
      
      







おわりに



今日、この変更を昼休みの終わり(約20〜30分)に実行しました。この時間の約3/4は、どこに置くかを決めるのに費やされました。 特にあなたが彼らと協力しなければならない場合、オープンソースプロジェクトを掘り下げることを恐れないでください。



ご清聴ありがとうございました。サイクルの次の記事であなたが書きたいことを聞いてうれしいです!



All Articles