private boolean addGeneratedFlexInitToFrame()

in compiler/src/main/java/org/apache/royale/compiler/internal/targets/RoyaleAppSWFTarget.java [1374:1726]


        private boolean addGeneratedFlexInitToFrame(final Collection<ICompilerProblem> problems, SWFFrame frame, Set<ICompilationUnit> emittedCompilationUnits, 
                boolean isAppFlexInfo, RoyaleApplicationFrame1Info frame1Info, FlexRSLInfo rslInfo) throws InterruptedException
        {
            ABCEmitter emitter = new ABCEmitter();
            emitter.visit(ABCConstants.VERSION_ABC_MAJOR_FP10, ABCConstants.VERSION_ABC_MINOR_FP10);
            
            
            String royaleInitClassNameString = getFlexInitClassName();
            
            Name royaleInitClassName = new Name(royaleInitClassNameString);
            
            Name stylesClassName = new Name(getStylesClassName());

            IDefinition objectDef = objectReference.resolve(royaleProject);
            if ((objectDef == null) || (!(objectDef instanceof ClassDefinition)))
                return false;
            ClassDefinition objectClassDef = (ClassDefinition)objectDef;
            
            Map<String, String> effectNameToTriggerMap = new TreeMap<String, String>();
            Map<String, Boolean> inheritingStyleMap = new TreeMap<String, Boolean>();            
            Map<ClassDefinition, String> remoteClassAliasMap =
                new TreeMap<ClassDefinition, String>(new Comparator<ClassDefinition>()
                {
                    @Override
                    public int compare(ClassDefinition o1, ClassDefinition o2)
                    {
                        return o1.getQualifiedName().compareTo(o2.getQualifiedName());
                    } 
                })
                {
                    private static final long serialVersionUID = 1L;

                    /**
                     *  Override so warning messages can be logged. 
                     */
                    @Override
                    public String put(ClassDefinition key, String value)
                    {
                        // check for duplicate values and log a warning if any remote 
                        // classes try to use the same alias.
                        if (containsValue(value))
                        {
                           for (Map.Entry<ClassDefinition,String> entry  : entrySet())
                           {
                               if (value != null && value.equals(entry.getValue()))
                               {
                                   problems.add(new ClassesMappedToSameRemoteAliasProblem(key.getQualifiedName(),
                                           entry.getKey().getQualifiedName(), value));
                                   break;
                               }
                           }
                        }
                        return super.put(key, value);
                    }
                };
                
            for (ICompilationUnit cu : emittedCompilationUnits)
            {
                Collection<IDefinition> visibleDefs = cu.getFileScopeRequest().get().getExternallyVisibleDefinitions();
                for (IDefinition visibleDef : visibleDefs)
                {
                    if (visibleDef instanceof ClassDefinition)
                    {
                        ClassDefinition visibleClass = (ClassDefinition) visibleDef;
                        IEffectDefinition[] effectDefinitions = visibleClass.getEffectDefinitions(royaleProject.getWorkspace());
                        for (IEffectDefinition effectDefinition : effectDefinitions)
                        {
                            // TODO create compiler problem if effect already has a trigger.
                            effectNameToTriggerMap.put(effectDefinition.getBaseName(), effectDefinition.getEvent());
                        }
                        
                        IStyleDefinition[] styleDefinitions = visibleClass.getStyleDefinitions(royaleProject.getWorkspace());
                        for (IStyleDefinition styleDefinition : styleDefinitions)
                        {
                            boolean isInheriting = styleDefinition.isInheriting();
                            // TODO create compiler problem if style definitions conflict
                            inheritingStyleMap.put(styleDefinition.getBaseName(), isInheriting);
                        }
                        
                        String remoteClassAlias = visibleClass.getRemoteClassAlias();
                        if (remoteClassAlias != null)
                            remoteClassAliasMap.put(visibleClass, remoteClassAlias);
                    }
                }
            }

            // Generate code for the constructor:
            // public function ClassName()
            // {
            //    super();
            // }
            InstructionList classITraitsInit = new InstructionList();
            classITraitsInit.addInstruction(ABCConstants.OP_getlocal0);
            classITraitsInit.addInstruction(ABCConstants.OP_constructsuper, 0);
            classITraitsInit.addInstruction(ABCConstants.OP_returnvoid);
            ClassGeneratorHelper classGen = new ClassGeneratorHelper(royaleProject, emitter, royaleInitClassName, 
                    objectClassDef, Collections.<Name>emptyList(), classITraitsInit);
            
            // Generate code for the static init method:
            // public static function init(mf : IFlexModuleFactory) : void
            // {
            //    new ChildManager(mf);
            //    var local2 : * = new StyleManagerImpl(mf);
            //
            //    // For each effect declared in the application:
            //    EffectManager.mx_internal::registerEffectTrigger(<effectName>, <eventName>);
            //
            //    // For each remote class alias declared in the application
            //    try 
            //    { 
            //        if (flash.net.getClassByAlias(<remote class alias>) != <class>) 
            //        { 
            //            flash.net.registerClassAlias(<remote class alias>, <class>); 
            //        } 
            //    } 
            //    catch (e:Error) 
            //    { 
            //        flash.net.registerClassAlias(<remote class alias>, <class>); 
            //    }
            //
            //    var local3 : * = [<names of all inheriting styles declared in the application>];
            //
            //    for each (var local0 : * in local3)
            //    {
            //        local2.registerInheritingStyle(local0);  // local2 is the style manager.
            //    }
            // }
            if (isAppFlexInfo)
            {
                MethodInfo initMethodInfo = new MethodInfo();
                initMethodInfo.setMethodName("FlexInit init method");
                initMethodInfo.setParamTypes(new Vector<Name>(Collections.singleton(new Name("Object"))));
                initMethodInfo.setReturnType(new Name(IASLanguageConstants.void_));
                IMethodVisitor initMethodVisitor = emitter.visitMethod(initMethodInfo);
                initMethodVisitor.visit();
                MethodBodyInfo initMethodBodyInfo = new MethodBodyInfo();
                initMethodBodyInfo.setMethodInfo(initMethodInfo);
                IMethodBodyVisitor initMethodBodyVisitor = initMethodVisitor.visitBody(initMethodBodyInfo);
                initMethodBodyVisitor.visit();
                
                // local0 = temp
                // local1 = module factory argument
                // local2 = style manager
                // local3 = inherited styles array
                InstructionList initMethod = new InstructionList();
                initMethod.addInstruction(ABCConstants.OP_returnvoid);
                
                initMethodBodyVisitor.visitInstructionList(initMethod);
                initMethodBodyVisitor.visitEnd();
                initMethodVisitor.visitEnd();
                
                ITraitVisitor initMethodTraitVisitor = 
                    classGen.getCTraitsVisitor().visitMethodTrait(ABCConstants.TRAIT_Method, new Name("init"), 0, initMethodInfo);
                initMethodTraitVisitor.visitStart();
                initMethodTraitVisitor.visitEnd();

                codegenInfoMethod(classGen, 
                        royaleProject.getCompatibilityVersion(),
                        getMainClassQName(),
                        getPreloaderClassReference(),
                        getRuntimeDPIProviderClassReference(),
                        splashScreenImage,
                        getRootNode(),
                        getTargetAttributes(),
                        royaleProject.getLocales(),
                        frame1Info,
                        accessibleClassNames,
                        getFlexInitClassName(),
                        getStylesClassName(),
                        targetSettings.getRuntimeSharedLibraries(),
                        rslInfo,
                        problems,
                        isAppFlexInfo,
                        isFlexSDKInfo,
                        remoteClassAliasMap);
                
            }
            else
            {
                MethodInfo initMethodInfo = new MethodInfo();
                initMethodInfo.setMethodName("FlexInit init method");
                initMethodInfo.setParamTypes(new Vector<Name>(Collections.singleton(iModuleFactoryReference.getMName())));
                initMethodInfo.setReturnType(new Name(IASLanguageConstants.void_));
                IMethodVisitor initMethodVisitor = emitter.visitMethod(initMethodInfo);
                initMethodVisitor.visit();
                MethodBodyInfo initMethodBodyInfo = new MethodBodyInfo();
                initMethodBodyInfo.setMethodInfo(initMethodInfo);
                IMethodBodyVisitor initMethodBodyVisitor = initMethodVisitor.visitBody(initMethodBodyInfo);
                initMethodBodyVisitor.visit();
                
                // local0 = temp
                // local1 = module factory argument
                // local2 = style manager
                // local3 = inherited styles array
                InstructionList initMethod = new InstructionList();
                
                // Since we don't need "this", we can kill local0, we'll use it later for something else.
                initMethod.addInstruction(ABCConstants.OP_kill, 0);
                initMethod.addInstruction(ABCConstants.OP_finddef, childManagerReference.getMName());
                initMethod.addInstruction(ABCConstants.OP_getlocal1);
                initMethod.addInstruction(ABCConstants.OP_constructprop, new Object[] { childManagerReference.getMName(), 1 });
                initMethod.addInstruction(ABCConstants.OP_pop);
                initMethod.addInstruction(ABCConstants.OP_finddef, styleManagerImplReference.getMName());
                initMethod.addInstruction(ABCConstants.OP_getlocal1);
                initMethod.addInstruction(ABCConstants.OP_constructprop, new Object[] { styleManagerImplReference.getMName(), 1 });
                initMethod.addInstruction(ABCConstants.OP_setlocal2);
                
                // register effects
                if (!effectNameToTriggerMap.isEmpty())
                {
                    IDefinition mxInternalDef = mxInternalReference.resolve(royaleProject);
                    if (!(mxInternalDef instanceof NamespaceDefinition))
                        return false;
                    
                    
                    IResolvedQualifiersReference registerEffectTriggerRef =
                        ReferenceFactory.resolvedQualifierQualifiedReference(royaleProject.getWorkspace(), (INamespaceDefinition)mxInternalDef, 
                                "registerEffectTrigger");
                    Name registerEffectTriggerName = registerEffectTriggerRef.getMName();
                    
                    initMethod.addInstruction(ABCConstants.OP_getlex, effectManagerReference.getMName());
                    
                    for (Map.Entry<String, String> effectEntry : effectNameToTriggerMap.entrySet())
                    {
                        initMethod.addInstruction(ABCConstants.OP_dup);  // copy the effectManager class closure
                        initMethod.addInstruction(ABCConstants.OP_pushstring, effectEntry.getKey());
                        initMethod.addInstruction(ABCConstants.OP_pushstring, effectEntry.getValue());
                        initMethod.addInstruction(ABCConstants.OP_callpropvoid, new Object[] { registerEffectTriggerName, 2 });
                    }
                    initMethod.addInstruction(ABCConstants.OP_pop);
                    
                }
                
                // Initialize AccessibilityClasses. Below is example code. Each
                // accessibility class found by the compiler will have its
                // enableAccessibility() method called.
                // 
                // if (Capabilities.hasAccessibility) {
                //    spark.accessibility.TextBaseAccImpl.enableAccessibility();
                //    mx.accessibility.UIComponentAccProps.enableAccessibility();
                //    spark.accessibility.ButtonBaseAccImpl.enableAccessibility();
                // }
                if (targetSettings.isAccessible())
                {
                    Name capabilitiesSlotName = capabilitiesReference.getMName();
                    initMethod.addInstruction(ABCConstants.OP_findpropstrict, capabilitiesSlotName);
                    initMethod.addInstruction(ABCConstants.OP_getproperty, capabilitiesSlotName);
                    initMethod.addInstruction(ABCConstants.OP_getproperty, new Name("hasAccessibility"));
                    Label accessibilityEnd = new Label();
                    initMethod.addInstruction(ABCConstants.OP_iffalse, accessibilityEnd);
    
                    IResolvedQualifiersReference enableAccessibilityReference = ReferenceFactory.packageQualifiedReference(royaleProject.getWorkspace(),
                            "enableAccessibility");            
                    Name enableAccessibilityName = enableAccessibilityReference.getMName();
                    Object[] enableAccessibilityCallPropOperands = new Object[] { enableAccessibilityName, 0 };
                    for (String accessibilityClassName : accessibleClassNames)
                    {
                        IResolvedQualifiersReference ref = ReferenceFactory.packageQualifiedReference(royaleProject.getWorkspace(),
                                accessibilityClassName);
                        Name accName = ref.getMName();
                        initMethod.addInstruction(ABCConstants.OP_getlex, accName);
                        initMethod.addInstruction(ABCConstants.OP_callproperty, enableAccessibilityCallPropOperands);
                        initMethod.addInstruction(ABCConstants.OP_pop);
                    }
    
                    initMethod.labelNext(accessibilityEnd);
                }
                
                // register class aliases
                if (!remoteClassAliasMap.isEmpty())
                {
                    Name getClassByAliasName = getClassByAliasReference.getMName();
                    Name registerClassAliasName = registerClassAliasReference.getMName();
                    Object[] getClassByAliasCallPropOperands = new Object[] { getClassByAliasName, 1 };
                    Object [] registerClassAliasCallPropOperands = new Object[] { registerClassAliasName, 2 };
                    for (Map.Entry<ClassDefinition, String> classAliasEntry : remoteClassAliasMap.entrySet())
                    {
                        Label tryLabel = new Label();
                        initMethod.labelNext(tryLabel);
                        initMethod.addInstruction(ABCConstants.OP_finddef, getClassByAliasName);
                        initMethod.addInstruction(ABCConstants.OP_pushstring, classAliasEntry.getValue());
                        initMethod.addInstruction(ABCConstants.OP_callproperty, getClassByAliasCallPropOperands);
                        Name classMName = classAliasEntry.getKey().getMName(royaleProject);
                        initMethod.addInstruction(ABCConstants.OP_getlex, classMName);
                        Label endTryLabel = new Label();
                        initMethod.addInstruction(ABCConstants.OP_ifeq, endTryLabel);
                        initMethod.addInstruction(ABCConstants.OP_finddef, registerClassAliasName);
                        initMethod.addInstruction(ABCConstants.OP_pushstring, classAliasEntry.getValue());
                        initMethod.addInstruction(ABCConstants.OP_getlex, classMName);
                        initMethod.addInstruction(ABCConstants.OP_callpropvoid, registerClassAliasCallPropOperands);
                        initMethod.labelNext(endTryLabel);
                        Label afterCatch = new Label();
                        initMethod.addInstruction(ABCConstants.OP_jump, afterCatch);
                        Label catchLabel = new Label();
                        initMethod.labelNext(catchLabel);
                        initMethod.addInstruction(ABCConstants.OP_pop);
                        initMethod.addInstruction(ABCConstants.OP_finddef, registerClassAliasName);
                        initMethod.addInstruction(ABCConstants.OP_pushstring, classAliasEntry.getValue());
                        initMethod.addInstruction(ABCConstants.OP_getlex, classMName);
                        initMethod.addInstruction(ABCConstants.OP_callpropvoid, registerClassAliasCallPropOperands);
                        initMethod.labelNext(afterCatch);
                        initMethodBodyVisitor.visitException(tryLabel, endTryLabel, catchLabel, 
                                new Name(IASLanguageConstants.Error), null);
                    }
                }
                
                // register inheriting styles
                if (!inheritingStyleMap.isEmpty())
                {
                    initMethod.addInstruction(ABCConstants.OP_getlex, stylesClassName);
                    int count = 0;
                    for (Map.Entry<String, Boolean> styleEntry : inheritingStyleMap.entrySet())
                    {
                        if (styleEntry.getValue().booleanValue())
                        {
                            ++count;
                            initMethod.addInstruction(ABCConstants.OP_pushstring, styleEntry.getKey());
                        }
                    }
                    
                    initMethod.addInstruction(ABCConstants.OP_newarray, count);
                    initMethod.addInstruction(ABCConstants.OP_setproperty, new Name("inheritingStyles"));
    
                }
    
                initMethod.addInstruction(ABCConstants.OP_returnvoid);
                
                initMethodBodyVisitor.visitInstructionList(initMethod);
                initMethodBodyVisitor.visitEnd();
                initMethodVisitor.visitEnd();
                
                ITraitVisitor initMethodTraitVisitor = 
                    classGen.getCTraitsVisitor().visitMethodTrait(ABCConstants.TRAIT_Method, new Name("init"), 0, initMethodInfo);
                initMethodTraitVisitor.visitStart();
                initMethodTraitVisitor.visitEnd();
            }
            classGen.finishScript();
            
            DoABCTag doABC = new DoABCTag();
            try
            {
                doABC.setABCData(emitter.emit());
            }
            catch (Exception e)
            {
                return false;
            }
            
            doABC.setName(getFlexInitClassName());
            frame.addTag(doABC);
            
            return true;
        }