public void collectReflectionData()

in compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/PackageFooterEmitter.java [262:541]


    public void collectReflectionData(ITypeNode tnode)
    {
    	JSRoyaleEmitter fjs = (JSRoyaleEmitter)getEmitter();
    	exportProperties = new ArrayList<String>();
    	exportSymbols = new ArrayList<String>();
		ICompilerProject project = getWalker().getProject();
    	Set<String> exportMetadata = Collections.<String> emptySet();
    	if (project instanceof RoyaleJSProject)
    	{
    		RoyaleJSProject fjsp = ((RoyaleJSProject)project);
    		if (fjsp.config != null)
    			exportMetadata = fjsp.config.getCompilerKeepCodeWithMetadata();
    	}
    	varData = new ArrayList<VariableData>();
    	accessorData = new ArrayList<AccessorData>();
    	methodData = new ArrayList<MethodData>();
    	/*
	     * Reflection
	     *
	     * @return {Object.<string, Function>}
	     */
        IDefinitionNode[] dnodes;
		String name;
		//bindables:
		HashMap<String, BindableVarInfo> bindableVars = getModel().getBindableVars();
        boolean isInterface = tnode instanceof IInterfaceNode;
	    if (!isInterface)
	        dnodes = ((IClassNode) tnode).getAllMemberNodes();
	    else
	        dnodes = ((IInterfaceNode) tnode).getAllMemberDefinitionNodes();
		reflectionKind = isInterface ? ReflectionKind.INTERFACE : ReflectionKind.CLASS;

        for (IDefinitionNode dnode : dnodes)
        {
            ModifiersSet modifierSet = dnode.getDefinition().getModifiers();
            boolean isStatic = (modifierSet != null && modifierSet
                    .hasModifier(ASModifier.STATIC));
            if ((dnode.getNodeID() == ASTNodeID.VariableID ||
            		dnode.getNodeID() == ASTNodeID.BindableVariableID))
            {
            	IVariableNode varNode = (IVariableNode)dnode;
                String ns = varNode.getNamespace();
				boolean isConst = varNode.isConst();
				if (isConst) {
					//todo consider outputting consts, none output for now
					continue;
				}
				//explicit exclusion from reflection data:
				if (getModel().suppressedExportNodes.contains(varNode)) {
					continue;
				}
				String altNS = null;
				if (ns != null &&  EmitterUtils.isCustomNamespace(ns)) {
					altNS = ((INamespaceDefinition)(((VariableNode) varNode).getNamespaceNode().resolve(getProject()))).getURI();
				}
                if (isInterface || (ns != null && ns.equals(IASKeywordConstants.PUBLIC )) || altNS != null)
                {
                	name = varNode.getName();

					IMetaTagsNode metaData = varNode.getMetaTags();
					//first deal with 'Bindable' upgrades to getters/setters
					if (!isInterface && bindableVars.containsKey(name)
							&& bindableVars.get(name).namespace.equals(IASKeywordConstants.PUBLIC)) {

						AccessorData bindableAccessor = new AccessorData();
						bindableAccessor.customNS = altNS;
						bindableAccessor.name = name;
						bindableAccessor.access = "readwrite";
						bindableAccessor.type = bindableVars.get(name).type;
						bindableAccessor.declaredBy = fjs.formatQualifiedName(tnode.getQualifiedName(), true);
						bindableAccessor.isStatic = isStatic;
						//attribute the metadata from the var definition to the Bindable Accessor implementation
						if (metaData != null)
						{
							IMetaTagNode[] tags = metaData.getAllTags();
							if (tags.length > 0)
								bindableAccessor.metaData = tags;
						}
						accessorData.add(bindableAccessor);
						//skip processing this varNode as a variable, it has now be added as an accessor
						continue;
					}


                	VariableData data = new VariableData();
                	varData.add(data);
                	data.name = name;
                	data.customNS = altNS;
					data.isStatic = isStatic;
					String qualifiedTypeName =	varNode.getVariableTypeNode().resolveType(getProject()).getQualifiedName();
					data.type = fjs.formatQualifiedName(qualifiedTypeName, true);

            	    if (metaData != null)
            	    {
            	    	IMetaTagNode[] tags = metaData.getAllTags();
            	    	if (tags.length > 0)
            	    	{
            	    		data.metaData = tags;
            	    		for (IMetaTagNode tag : tags)
            	    		{
            	    			String tagName =  tag.getTagName();
            	    			if (exportMetadata.contains(tagName))
            	    			{
            	    				if (data.isStatic)
            	    					exportSymbols.add(data.name);
            	    				else
                	    				exportProperties.add(data.name);
            	    			}
            	    		}
            	    	}
            	    }
                }
            }
        }

        if (getModel().hasStaticBindableVars()) {
			//we have an implicit implementation of a static event dispatcher
			//so add the 'staticEventDispatcher' accessor to the reflection data
			AccessorData staticEventDispatcher = new AccessorData();
			staticEventDispatcher.name = BindableEmitter.STATIC_DISPATCHER_GETTER;
			staticEventDispatcher.access = "readonly";
			staticEventDispatcher.type = fjs.formatQualifiedName(BindableEmitter.DISPATCHER_CLASS_QNAME, true);
			staticEventDispatcher.declaredBy = fjs.formatQualifiedName(tnode.getQualifiedName(), true);
			staticEventDispatcher.isStatic = true;
			accessorData.add(staticEventDispatcher);
		}
     
	    HashMap<String, AccessorData> instanceAccessorMap = new HashMap<String, AccessorData>();
		HashMap<String, AccessorData> staticAccessorMap = new HashMap<String, AccessorData>();
        for (IDefinitionNode dnode : dnodes)
        {
            ModifiersSet modifierSet = dnode.getDefinition().getModifiers();
            boolean isStatic = (modifierSet != null && modifierSet
                    .hasModifier(ASModifier.STATIC));

			HashMap<String, AccessorData> accessorMap = isStatic ? staticAccessorMap : instanceAccessorMap;
            if ((dnode.getNodeID() == ASTNodeID.GetterID ||
            		dnode.getNodeID() == ASTNodeID.SetterID))
            {
            	IFunctionNode fnNode = (IFunctionNode)dnode;
                String ns = fnNode.getNamespace();
                boolean suppressed = getModel().suppressedExportNodes.contains(fnNode);
	
				String altNS = null;
				if (ns != null &&  EmitterUtils.isCustomNamespace(ns)) {
					altNS = ((INamespaceDefinition)(((FunctionNode) fnNode).getNamespaceNode().resolve(getProject()))).getURI();
				}

                if (isInterface || (ns != null && ns.equals(IASKeywordConstants.PUBLIC)) || altNS != null)
                {
					String accessorName = fnNode.getName();
					String nameKey = altNS!=null? altNS+accessorName : accessorName;
                	AccessorData data = accessorMap.get(nameKey);
					if (data == null) {
						if (suppressed) continue;
						data = new AccessorData();
					} else {
						if (suppressed) {
							accessorData.remove(data);
							accessorMap.remove(nameKey);
							continue;
						}
					}
                	data.name = accessorName;
					data.customNS = altNS;
                	if (!accessorData.contains(data)) accessorData.add(data);
            	    if (dnode.getNodeID() == ASTNodeID.GetterID) {
						String qualifiedTypeName =	fnNode.getReturnType();
						if (!(qualifiedTypeName.equals("") || qualifiedTypeName.equals("void"))) {
								qualifiedTypeName = fnNode.getReturnTypeNode().resolveType(getProject()).getQualifiedName();
						}
						data.type = fjs.formatQualifiedName(qualifiedTypeName, true);
						if (data.access == null) {
							data.access = "readonly";
						} else data.access = "readwrite";
					}
            	    else {
						data.type = ((SetterNode)fnNode).getVariableTypeNode().resolveType(getProject()).getQualifiedName();
						if (data.access == null) {
							data.access = "writeonly";
						} else data.access = "readwrite";
					}
                	accessorMap.put(nameKey, data);
            	    data.type = fjs.formatQualifiedName(data.type, true);
            	    IClassNode declarer = (IClassNode)fnNode.getAncestorOfType(IClassNode.class);
            	    String declarant = fjs.formatQualifiedName(tnode.getQualifiedName(), true);
            	    if (declarer != null)
            	    	declarant = fjs.formatQualifiedName(declarer.getQualifiedName(), true);
            	    data.declaredBy = declarant;
					data.isStatic = isStatic;
            	    IMetaTagsNode metaData = fnNode.getMetaTags();
            	    if (metaData != null)
            	    {
            	    	IMetaTagNode[] tags = metaData.getAllTags();
            	    	if (tags.length > 0)
            	    	{
            	    		data.metaData = tags;
        	    			/* accessors don't need exportProp since they are referenced via the defineProp data structure
            	    		for (IMetaTagNode tag : tags)
            	    		{
            	    			String tagName =  tag.getTagName();
            	    			if (exportMetadata.contains(tagName))
            	    			{
            	    				if (data.isStatic)
            	    					exportSymbols.add(data.name);
            	    				else
                	    				exportProperties.add(data.name);
            	    			}
            	    		}
            	    		*/
            	    	}
            	    }
                }
            }
        }
        for (IDefinitionNode dnode : dnodes)
        {
            ModifiersSet modifierSet = dnode.getDefinition().getModifiers();
            boolean isStatic = (modifierSet != null && modifierSet
                    .hasModifier(ASModifier.STATIC));
            if (dnode.getNodeID() == ASTNodeID.FunctionID )
            {
            	IFunctionNode fnNode = (IFunctionNode)dnode;
                String ns = fnNode.getNamespace();
	
				String altNS = null;
				if (ns != null && EmitterUtils.isCustomNamespace(ns)) {
					altNS = ((INamespaceDefinition)(((FunctionNode) fnNode).getNamespaceNode().resolve(getProject()))).getURI();
				}
                
                if (isInterface || (ns != null && ns.equals(IASKeywordConstants.PUBLIC)) || altNS != null)
                {
                	if (getModel().suppressedExportNodes.contains(fnNode)) continue;
                	MethodData data = new MethodData();
					data.isStatic = isStatic;
                	methodData.add(data);
                	data.name = fnNode.getName();
                	data.customNS = altNS;
					String qualifiedTypeName =	fnNode.getReturnType();
					if (!(qualifiedTypeName.equals("") || qualifiedTypeName.equals("void"))) {
							qualifiedTypeName = fnNode.getReturnTypeNode().resolveType(getProject()).getQualifiedName();
					}
					data.type = fjs.formatQualifiedName(qualifiedTypeName, true);
            	    ITypeNode declarer;
            	    if (isInterface)
            	    	declarer = (IInterfaceNode)fnNode.getAncestorOfType(IInterfaceNode.class);
            	    else
            	    	declarer = (IClassNode)fnNode.getAncestorOfType(IClassNode.class);
            	    String declarant = fjs.formatQualifiedName(tnode.getQualifiedName(), true);
            	    if (declarer != null)
            	    	declarant = fjs.formatQualifiedName(declarer.getQualifiedName(), true);
            	    data.declaredBy = declarant;
            	    IMetaTagsNode metaData = fnNode.getMetaTags();
            	    if (metaData != null)
            	    {
            	    	IMetaTagNode[] tags = metaData.getAllTags();
            	    	if (tags.length > 0)
            	    	{
            	    		data.metaData = tags;
            	    		for (IMetaTagNode tag : tags)
            	    		{
            	    			String tagName =  tag.getTagName();
            	    			if (exportMetadata.contains(tagName))
            	    			{
            	    				if (data.isStatic)
            	    					exportSymbols.add(data.name);
            	    				else
                	    				exportProperties.add(data.name);
            	    			}
            	    		}
            	    	}
            	    }
					IParameterNode[] paramNodes = fnNode.getParameterNodes();
					if (paramNodes != null) {
						data.parameters = paramNodes;
					}
				}
            }
        }
    }