* {@inheritDoc}
*/
@Override
public byte[] buildABC(ICompilerProject project, Collection<ICompilerProblem> problems)
{
ABCEmitter emitter = new ABCEmitter();
final String classQName = data.getQName();
Name className = new Name(classQName);
IDefinition baseClass = project.resolveQNameToDefinition(skinClass);
assert (baseClass instanceof ClassDefinition) : "skinClass does not resolve to a class";
ClassDefinition baseClassDef = (ClassDefinition)baseClass;
Collection<Name> implementedInterfaces = new ImmutableList.Builder<Name>()
.add(iBorderReference.getMName())
.add(iFlexDisplayObjectReference.getMName())
.add(iFlexAssetReference.getMName())
.build();
//FIXME: move this to ClassGeneratorHelper
Namespace privateNs = new Namespace(ABCConstants.CONSTANT_PrivateNs, className.getSingleQualifier().getName() + ":" + className.getBaseName());
// generate the constructor:
// public function $className() extends $baseClassDef implements IBorder, IFlexDisplayObject, IFlexAsset
// {
// super();
InstructionList classITraitsInit = new InstructionList();
classITraitsInit.addInstruction(ABCConstants.OP_getlocal0);
classITraitsInit.addInstruction(ABCConstants.OP_constructsuper, 0);
// generate:
// _measuredWidth = width;
Name _measuredWidth = null;
if (skinClassInfo.needsMeasuredWidth)
{
Name width = new Name("width");
classITraitsInit.addInstruction(ABCConstants.OP_getlocal0);
classITraitsInit.addInstruction(ABCConstants.OP_getlocal0);
classITraitsInit.addInstruction(ABCConstants.OP_getproperty, width);
_measuredWidth = new Name(ABCConstants.CONSTANT_Qname, new Nsset(privateNs), "_measuredWidth");
classITraitsInit.addInstruction(ABCConstants.OP_initproperty, _measuredWidth);
}
// generate:
// _measuredHeight = height;
Name _measuredHeight = null;
if (skinClassInfo.needsMeasuredHeight)
{
Name height = new Name("height");
classITraitsInit.addInstruction(ABCConstants.OP_getlocal0);
classITraitsInit.addInstruction(ABCConstants.OP_getlocal0);
classITraitsInit.addInstruction(ABCConstants.OP_getproperty, height);
_measuredHeight = new Name(ABCConstants.CONSTANT_Qname, new Nsset(privateNs), "_measuredHeight");
classITraitsInit.addInstruction(ABCConstants.OP_initproperty, _measuredHeight);
}
// generate: TODO: currently we don't wrap this call in a try/catch, as it
// seems unnecessary. Change if need be.
// try
// {
// name = NameUtil.createUniqueName(this);
// }
// catch(e:Error)
// {
// }
if (!skinClassInfo.flexMovieClipOrSprite)
{
Name name = new Name("name");
classITraitsInit.addInstruction(ABCConstants.OP_getlocal0);
Name nameUtil = ReferenceFactory.packageQualifiedReference(workspace, UTILS_PACKAGE + ".NameUtil").getMName();
classITraitsInit.addInstruction(ABCConstants.OP_getlex, nameUtil);
classITraitsInit.addInstruction(ABCConstants.OP_getlocal0);
Object[] createUniqueName = new Object[] { new Name("createUniqueName"), 1 };
classITraitsInit.addInstruction(ABCConstants.OP_callproperty, createUniqueName);
classITraitsInit.addInstruction(ABCConstants.OP_initproperty, name);
}
// finish the constructor
classITraitsInit.addInstruction(ABCConstants.OP_returnvoid);
TypeDefinitionBase numberDef = (TypeDefinitionBase)project.getBuiltinType(BuiltinType.NUMBER);
Name numberName = numberDef.getMName(project);
// add all the member variables to the class
ClassGeneratorHelper classGen = new ClassGeneratorHelper(project, emitter, className, baseClassDef, implementedInterfaces, classITraitsInit);
// generate:
// public function get borderMetrics():EdgeMetrics
// {
// if (scale9Grid == null)
// {
// return EdgeMetrics.EMPTY;
// }
// else
// {
// return new EdgeMetrics(scale9Grid.left,
// scale9Grid.top,
// Math.ceil(measuredWidth - scale9Grid.right),
// Math.ceil(measuredHeight - scale9Grid.bottom));
// }
// }
if (skinClassInfo.needsIBorder && skinClassInfo.needsBorderMetrics)
{
InstructionList body = new InstructionList();
Name scale9Grid = new Name("scale9Grid");
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_getproperty, scale9Grid);
Label trueLabel = new Label();
body.addInstruction(ABCConstants.OP_iftrue, trueLabel);
Name edgeMetrics = ReferenceFactory.packageQualifiedReference(workspace, CORE_PACKAGE + ".EdgeMetrics").getMName();
body.addInstruction(ABCConstants.OP_getlex, edgeMetrics);
body.addInstruction(ABCConstants.OP_getproperty, new Name("EMPTY"));
body.addInstruction(ABCConstants.OP_returnvalue);
body.labelNext(trueLabel);
body.addInstruction(ABCConstants.OP_findpropstrict, edgeMetrics);
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_getproperty, scale9Grid);
body.addInstruction(ABCConstants.OP_getproperty, new Name("left"));
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_getproperty, scale9Grid);
body.addInstruction(ABCConstants.OP_getproperty, new Name("top"));
Name math = new Name("Math");
body.addInstruction(ABCConstants.OP_getlex, math);
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_getproperty, new Name("measuredWidth"));
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_getproperty, scale9Grid);
body.addInstruction(ABCConstants.OP_getproperty, new Name("right"));
body.addInstruction(ABCConstants.OP_subtract);
Object[] ceil = new Object[] {new Name("ceil"), 1};
body.addInstruction(ABCConstants.OP_callproperty, ceil);
body.addInstruction(ABCConstants.OP_getlex, math);
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_getproperty, new Name("measuredHeight"));
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_getproperty, scale9Grid);
body.addInstruction(ABCConstants.OP_getproperty, new Name("bottom"));
body.addInstruction(ABCConstants.OP_subtract);
body.addInstruction(ABCConstants.OP_callproperty, ceil);
body.addInstruction(ABCConstants.OP_constructprop, new Object[] {edgeMetrics, 4});
body.addInstruction(ABCConstants.OP_returnvalue);
classGen.addITraitsGetter(new Name("borderMetrics"), edgeMetrics, body);
}
if (skinClassInfo.needsIFlexDisplayObject)
{
// generate:
// public function get measuredWidth():Number
// {
// return _measuredWidth;
// }
if (skinClassInfo.needsMeasuredWidth)
{
InstructionList body = new InstructionList();
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_getproperty, _measuredWidth);
body.addInstruction(ABCConstants.OP_returnvalue);
classGen.addMemberVariable(_measuredWidth, numberName);
classGen.addITraitsGetter(new Name("measuredWidth"), numberName, body);
}
// generate:
// public function get measuredHeight():Number
// {
// return _measuredHeight;
// }
if (skinClassInfo.needsMeasuredHeight)
{
InstructionList body = new InstructionList();
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_getproperty, _measuredHeight);
body.addInstruction(ABCConstants.OP_returnvalue);
classGen.addMemberVariable(_measuredHeight, numberName);
classGen.addITraitsGetter(new Name("measuredHeight"), numberName, body);
}
// generate:
// public function move(x:Number, y:Number):void
// {
// this.x = x;
// this.y = y;
// }
if (skinClassInfo.needsMove)
{
InstructionList body = new InstructionList();
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_getlocal1);
body.addInstruction(ABCConstants.OP_setproperty, new Name("x"));
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_getlocal2);
body.addInstruction(ABCConstants.OP_setproperty, new Name("y"));
body.addInstruction(ABCConstants.OP_returnvoid);
Collection<Name> paramTypes = new ImmutableList.Builder<Name>()
.add(numberName)
.add(numberName)
.build();
classGen.addITraitsMethod(new Name("move"), paramTypes, new Name("void"), Collections.<Object>emptyList(), false, false, false, body);
}
// generate:
// public function setActualSize(newWidth:Number, newHeight:Number):void
// {
// if (width != newWidth)
// {
// width = newWidth;
// }
// if (height != newHeight)
// {
// height = newHeight;
// }
// }
if (skinClassInfo.needsSetActualSize)
{
InstructionList body = new InstructionList();
Name width = new Name("width");
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_getproperty, width);
body.addInstruction(ABCConstants.OP_getlocal1);
Label trueLabel = new Label();
body.addInstruction(ABCConstants.OP_ifeq, trueLabel);
body.addInstruction(ABCConstants.OP_findproperty, width);
body.addInstruction(ABCConstants.OP_getlocal1);
body.addInstruction(ABCConstants.OP_setproperty, width);
body.labelNext(trueLabel);
Name height = new Name("height");
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_getproperty, height);
body.addInstruction(ABCConstants.OP_getlocal2);
trueLabel = new Label();
body.addInstruction(ABCConstants.OP_ifeq, trueLabel);
body.addInstruction(ABCConstants.OP_findproperty, height);
body.addInstruction(ABCConstants.OP_getlocal2);
body.addInstruction(ABCConstants.OP_setproperty, height);
body.labelNext(trueLabel);
body.addInstruction(ABCConstants.OP_returnvoid);
Collection<Name> paramTypes = new ImmutableList.Builder<Name>()
.add(numberName)
.add(numberName)
.build();
classGen.addITraitsMethod(new Name("setActualSize"), paramTypes, new Name("void"), Collections.<Object>emptyList(), false, false, false, body);
}
}
// generate:
// override public function toString():String
// {
// return NameUtil.displayObjectToString(this);
// }
if (!skinClassInfo.flexMovieClipOrSprite)
{
InstructionList body = new InstructionList();
body.addInstruction(ABCConstants.OP_getlocal0);
body.addInstruction(ABCConstants.OP_pushscope);
Name nameUtil = ReferenceFactory.packageQualifiedReference(workspace, UTILS_PACKAGE + ".NameUtil").getMName();
body.addInstruction(ABCConstants.OP_getlex, nameUtil);
body.addInstruction(ABCConstants.OP_getlocal0);
Object[] displayObjectToString = new Object[] { new Name("displayObjectToString"), 1 };
body.addInstruction(ABCConstants.OP_callproperty, displayObjectToString);
body.addInstruction(ABCConstants.OP_returnvalue);
TypeDefinitionBase stringDef = (TypeDefinitionBase)project.getBuiltinType(BuiltinType.STRING);
Name stringName = stringDef.getMName(project);
classGen.addITraitsMethod(new Name("toString"), Collections.<Name>emptyList(), stringName, Collections.<Object>emptyList(), false, false, true, body);
}
classGen.finishScript();
try
{
return emitter.emit();
}
catch (Exception e)
{
problems.add(new InternalCompilerProblem(e));
return null;