MXML संकलक। भाग 2. गैर-स्ट्रिंग पैरामीटर इनिशियलाइज़र

हेलो, हेब्र!

पिछले लेख में, मैंने फ्लेक्स कंपाइलर (एमएक्सएमएल के संदर्भ में) के कुछ शैक्षिक कार्यक्रम को अंजाम दिया और एमएक्सएमएल में कक्षाओं के साथ काम करने की समस्याओं से छुटकारा पाने के बारे में बात की, जिनके लिए निर्माण मापदंडों की आवश्यकता होती है। अब हम इस मुद्दे के दूसरे पक्ष का विश्लेषण करेंगे - बाइंडिंग तंत्र का उपयोग किए बिना कस्टम मानों (उदाहरण के लिए, स्थिरांक) के लिए पैरामीटर सेट करना (हालाँकि यह इसके समान है)।


उद्घाटन टिप्पणी

मैं इस तथ्य के लिए अग्रिम रूप से माफी मांगना चाहता हूं कि यह लेख बाद में मैंने कहा था - शाब्दिक रूप से मेरे द्वारा काम पर रखे जाने के अगले दिन, और बस कोई समय नहीं था :) अब सब कुछ हल हो गया है, और मैं लेखों की श्रृंखला जारी रखने के लिए तैयार हूं।

मुझे लगता है कि फ्लेक्स के साथ काम करने वाले सभी लोग एक या दूसरे तरीके से कुछ इस तरह से आए:
<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; } 

क्या संपत्ति को स्थिर के रूप में निर्दिष्ट करने के ऐसे तुच्छ कार्य के लिए बहुत सारे कोड नहीं हैं, जो परिभाषा से नहीं बदलता है?

चलो करते हैं!


हमारा लक्ष्य एक पिछड़े संगत संशोधन करना है जो नागरिक IDEs में स्वत: पूर्ण का समर्थन करेगा, साथ ही फ्लेक्स प्रोग्रामर के लिए भी परिचित होगा। उपरोक्त सभी आवश्यकताओं को देखते हुए, मैंने फैसला किया कि समाधान इस तरह दिखेगा:
 <TextField xmlns="flash.text.*" autoSize="${TextFieldAutoSize.CENTER}" /> 

डॉलर प्रतीक का उपयोग करने का विचार एएनटी-लिपियों से आया है, यह सुविधाजनक और स्पष्ट है, और यह पहले से ही अच्छे आधे फ्लैशर्स से परिचित है।

सच कहूँ तो, मैंने स्ट्रिंग "@ {", क्योंकि की प्रविष्टि के लिए java.flex2.compiler.mxml.lang पैकेज (इसमें क्यों? इसमें पहला लेख देखें?) में सभी वर्गों की खोज करके प्रक्रिया शुरू की। यह उसके साथ है कि तथाकथित दो-तरफा बाइंडिंग शुरू होती है, और हमारा कार्यान्वयन उन पर आधारित हो सकता है। और मैं भाग्यशाली हो गया! ParseBindingExpression विधि को java.flex2.compiler.mxml.lang.TextPserser में तुरंत पता चला।

बाइंडिंग एक्सप्रेशन के प्रकारों का उपयोग बाइंडिंग अभिव्यक्ति को दर्शाने के लिए किया जाता है, इसलिए, सादृश्य द्वारा, हम इसके आगे एक ExactValueExpression क्लास बनाएंगे (पैकेज flex2.compiler.mxml.rep में):
 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(); } 

हम चींटी कंपाइलर कमांड के साथ प्रोजेक्ट को इकट्ठा करते हैं, 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 समय यह निर्धारित करने में खर्च किया गया कि कुछ कहाँ रखा जाए। ओपन सोर्स प्रोजेक्ट में तल्लीन होने से डरो मत, उन्हें संशोधित करने और बेहतर करने की कोशिश करें, खासकर यदि आपको उनके साथ काम करना है।

ध्यान देने के लिए आप सभी का धन्यवाद, मुझे यह सुनकर खुशी होगी कि आप चक्र के अगले लेखों में क्या लिखना चाहते हैं!

Source: https://habr.com/ru/post/In131434/


All Articles