📜 ⬆️ ⬇️

Adding Designer Parameters to the MXML Flex Compiler

April 26, 2007. Adobe makes a statement that the Flex Framework is being translated to open source. This news caused a storm of applause among the flashers of the whole world, that fundamentally new frameworks based on it will appear, but this did not go beyond a couple of projects.

At that time I did projects using Flex, and the more projects became, the more I did not like some of the nuances of its internal structure.
I think everyone who has worked with Flex knows its problems, as well as the poor quality of the code already written and generated from MXML, so I decided to intervene in this process in order to clean up the order and understand the Flex compiler device, and I started by adding “sugar” to MXML, trying to make it as strong as possible in the spirit of the other features of Adobe’s brainchild. Two years later, I decided to share my knowledge with you.

Foreword


I will not give a description of the process of checking out the FlexSDK project from the SVN repository, just leave a link to the description of this process.

At the time of this writing, the latest version was Flex 4.5.1 (4.5.1.21328), so it's worth it to build on it.
')
When I first started to dig the compiler, I didn’t have enough knowledge of Java, so I had to be guided by common sense, all the changes were made in Notepad ++.
I also advise you to use your favorite Java IDE, because without blackjack and whores “Goto Declaration” and “Find Usages” was very, very hard.

What's inside


Unfortunately, one article is not enough to cover the device of the entire compiler, so in this article I will tell only about a small part of it - the MXML translator.
All sources related to it are in the modules / compiler / src / java / flex2 / compiler / mxml folder:





From theory to practice!


I myself did not expect so much “theory” to turn out, but it will greatly help you understand where, what and why. And now let's go straight to what it was all about - the ability to specify constructor parameters for MXML objects.

Many classes in AS3 have the required constructor parameters, because of which these classes have to be wrapped into objects without parameters, or created from in the <fx: Script /> tag, which also violates our usual MXML view, so I suggest making this implementation :
<?xml version="1.0"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"> <fx:Declarations> <Timer xmlns="flash.utils.*" new="1000, 1" /> </fx:Declarations> </s:Application> 


The choice of the new keyword is due to the fact that in AS3 we can never create a property named new, since it is reserved. What is passed to new will be inserted into parentheses when initializing our object, in this case,
 new Timer(1000, 1); 


Pass validation

To validator missed our new attribute, we must add it to the same (for example, includeIn, excludeFrom, and so on). A text search showed that this attribute is first declared in lang / StandardDefs.java, and then checked in builder / ComponentBuilder.java (isSpecialAttribute method)

add to StandardDefs
 public static final String PROP_NEW = "new"; 

after 310 lines:
 public static final String PROP_ID = "id"; 


As well as in ComponentBuilder (isSpecialAttribute method)
 if (namespace.length() == 0 || namespace.equals(document.getLanguageNamespace())) { if (StandardDefs.PROP_ID.equals(localPart) || StandardDefs.PROP_NEW.equals(localPart) || StandardDefs.PROP_INCLUDE_STATES.equals(localPart) || StandardDefs.PROP_EXCLUDE_STATES.equals(localPart) || StandardDefs.PROP_ITEM_CREATION_POLICY.equals(localPart) || StandardDefs.PROP_ITEM_DESTRUCTION_POLICY.equals(localPart)) { isSpecial = true; } } 

Now the validator does not swear at the MXML tags new attribute.

We register a new property with an object model.

So, our attribute has a place to be, but do we need to save its value somewhere? For this we have Model.java.
Create in rep / Model.java getter / setters for the constructor parameters, adding a property and two methods to the class:
 protected String constructorParams; public void setConstructorParams(String value) { constructorParams = value; } public String getConstructorParams() { return constructorParams; } 


We will use this property in the registerBodel method (Node node, Model model, boolean topLevel) of AbstractBuilder.java class (line 1617):
 protected void registerModel(Node node, Model model, boolean topLevel) { String id = (String)getLanguageAttributeValue(node, StandardDefs.PROP_ID); String newValue = (String)getLanguageAttributeValue(node, StandardDefs.PROP_NEW); // get the comment from the node and store in the model if(node.comment != null) { // if generate ast if false, lets not scan the tokens here because they will be scanned later in asc scanner. // we will go the velocity template route if(!mxmlConfiguration.getGenerateAbstractSyntaxTree()) { model.comment = node.comment; } else { model.comment = MxmlCommentUtil.commentToXmlComment(node.comment); } } if(newValue != null) { model.setConstructorParams(newValue); } registerModel(id, model, topLevel); } 


We use the attribute in code generation

The smallest part remains - to add our attribute to the place where the object is created, passing it to AS IS in the brackets of the constructor. Said - done!

The class rep / init / ValueInitializer.java, the getDefinitionBody () method, immediately after the Adobe TODO on line 467:
 else { // TODO confirm the availability of a 0-arg ctor!! but do it upstream from here, like when Model is built stringBuilder.append("new " + selfTypeName + "("); if(self.getConstructorParams() != null) { stringBuilder.append(self.getConstructorParams()); } stringBuilder.append(")"); } 


Compilation

Now, going to the console in the root folder of the framework (trunk, if you downloaded the entire repository), it remains to run the build project, for which we enter (you must have ant):
 BSiDeUp-Mac-mini:trunk bsideup$ ant build 

You can go and make yourself a coffee / put dry crackers / lean back on the chair (underline the necessary), because The process will take about 5 minutes.
(Hint: after the 1st build it will be possible to run only ant compiler, then only the compiler module will be built)

After waiting for something like this:
  main: [echo] ant main target completed on 09/16/2011 11:54:25 AM BUILD SUCCESSFUL Total time: 5 minutes 33 seconds 

We rejoice and rejoice, otherwise - we re-read the manual of the person and look for what we have missed.

Conclusion


Now you can confidently specify our framework as the Flex Framework Location in your favorite IDE, thereby starting to use a modified compiler that supports the new attribute!

This time we made a backward-compatible change that allows you to compile other projects using MXML without problems, and in the next article, if the topic is interesting, I will tell you how to change the standard behavior of MXML, making the programmer’s life even easier, but losing backward compatibility.

For those who are interested in the result, not the process, I provide a link to the ready-made mxmlc.jar file, just download the Flex SDK 4.5 and replace it with the file $ {FLEX_SDK_DIR} /lib/mxmlc.jar.

Thanks for attention.

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


All Articles