private void generateExternsReport()

in compiler-jx/src/main/java/org/apache/royale/compiler/clients/MXMLJSCRoyale.java [547:761]


    private void generateExternsReport(File externsReportFile,
			List<ICompilationUnit> reachableCompilationUnits,
			ProblemQuery problems) {
        
        if (config.isVerbose())
        {
            System.out.println("Generating externs report: " + externsReportFile.getAbsolutePath());
        }
        
    	ArrayList<String> packageNames = new ArrayList<String>();
    	ArrayList<String> partNames = new ArrayList<String>();
    	
    	StringBuilder sb = new StringBuilder();
        sb.append("/**\n");
        sb.append(" * Generated by Apache Royale Compiler\n");
        sb.append(" *\n");
        sb.append(" * @fileoverview\n");
        sb.append(" * @externs\n");
        sb.append(" *\n");
        // need to suppress access controls so access to protected/private from defineProperties
        // doesn't generate warnings.
        sb.append(" * @suppress {checkTypes|accessControls}\n");
        sb.append(" */\n");

    	for (ICompilationUnit cu : reachableCompilationUnits)
    	{
    		if (project.isExternalLinkage(cu)) continue;
    		
            List<IDefinition> dp = cu.getDefinitionPromises();

            if (dp.size() == 0)
                return;

            IDefinition def = dp.get(0);
            IDefinition actualDef = ((DefinitionPromise) def).getActualDefinition();
            if (actualDef.getPackageName().contains("goog")) continue;
            if (actualDef instanceof ClassDefinition)
            {
            	sb.append("\n\n");
            	ClassDefinition cdef = (ClassDefinition)actualDef;
            	String pkgName = cdef.getPackageName();
            	if (pkgName.length() > 0 && !packageNames.contains(pkgName))
            	{
            		packageNames.add(pkgName);
            		String[] parts = pkgName.split("\\.");
            		String current = "";
            		boolean firstOne = true;
            		for (String part : parts)
            		{
            			current += part;
            			if (partNames.contains(current))
            			{
            				firstOne = false;
        	                current += ".";
            				continue;
            			}            			
            			partNames.add(current);
        				sb.append("/**\n * @suppress {duplicate}\n * @const\n */\n");
            			if (firstOne)
            			{
            				sb.append("var ");
            				firstOne = false;
            			}
            			sb.append(current);
            			sb.append(" = {}");
            			sb.append(ASEmitterTokens.SEMICOLON.getToken() + "\n");
    	                current += ".";
            		}
            	}
            	sb.append("\n\n");
            	sb.append("/**\n");
            	sb.append(" * @constructor\n");
            	String baseString = cdef.getBaseClassAsDisplayString();
            	if (baseString.length() > 0)
            		sb.append(" * @extends {" + baseString + "}\n");
            	String[] ifaces = cdef.getImplementedInterfacesAsDisplayStrings();
            	for (String iface : ifaces)
            		sb.append(" * @implements {" + iface + "}\n");
            	sb.append(" */\n");
            	if (pkgName.length() == 0)
                    sb.append("function " + cdef.getQualifiedName() + "() {}\n");
            	else
            		sb.append(cdef.getQualifiedName() + " = function() {}\n");
                
            	ASScope cscope = cdef.getContainedScope();
            	Collection<IDefinitionSet> defSets = cscope.getAllLocalDefinitionSets();
            	IDefinitionSet[] arrayOfDefSets = new IDefinitionSet[defSets.size()];
            	defSets.toArray(arrayOfDefSets);
            	for (IDefinitionSet defSet : arrayOfDefSets)
            	{
            		int n = defSet.getSize();
            		for (int i = 0; i < n; i++)
            		{
            			IDefinition api = defSet.getDefinition(i);
            			String apiName = api.getBaseName();
            			if (apiName.startsWith("#")) continue; // invalid in externs
            			if (!api.isOverride() && (api.isProtected() || api.isPublic()))
            			{
            				if (!(api instanceof FunctionDefinition) ||
            						api instanceof AccessorDefinition)
            				{
                            	sb.append("\n\n");
                            	sb.append("/**\n");
                            	sb.append(" * @type {" + getJSType(api.getTypeAsDisplayString()) + "}\n");
                            	sb.append(" */\n");
                            	sb.append(cdef.getQualifiedName() + ".");
                            	if (!api.isStatic())
                            		sb.append("prototype.");
                            	sb.append(api.getBaseName() + ";\n");            					
            				}
            				else
            				{
            					FunctionDefinition method = (FunctionDefinition)api;
            					ParameterDefinition[] params = method.getParameters();
                            	sb.append("\n\n");
                            	sb.append("/**\n");
                            	for (ParameterDefinition param : params)
                            	{
                            		if (param.getBaseName().isEmpty())
                            			sb.append(" * @param {*=} opt_rest\n");
                            		else
                            			sb.append(" * @param {" + getJSType(param.getTypeAsDisplayString()) + "} " + param.getBaseName() + "\n");
                            	}
                            	String ret = getJSType(method.getReturnTypeAsDisplayString());
                            	if (!ret.equals("void"))
                            		sb.append(" * @returns {" + ret + "}\n");
                            	sb.append(" */\n");
                            	sb.append(cdef.getQualifiedName() + ".");
                            	if (!api.isStatic())
                            		sb.append("prototype.");
                            	sb.append(api.getBaseName());
                            	sb.append(" = function(");
                            	int m = params.length;
                            	for (int j = 0; j < m; j++)
                            	{
                            		if (j > 0)
                            			sb.append(",");
                            		if (params[j].getBaseName().isEmpty())
                            			sb.append("opt_rest");
                            		else
                            			sb.append(params[j].getBaseName());
                            	}
                            	sb.append(") {");
                            	if (!ret.equals("void"))
                            	{
                            		if (ret.equals("number"))
                            			sb.append(" return 0; ");
                            		else if (ret.equals("boolean"))
                            			sb.append(" return false; ");
                            		else
                            			sb.append(" return null; ");
                            	}
                            	sb.append("};\n");
            				}
            			}
            		}
            	}            	
            }
            else if (actualDef instanceof InterfaceDefinition)
            {
            	sb.append("\n\n");
            	InterfaceDefinition cdef = (InterfaceDefinition)actualDef;
            	String pkgName = cdef.getPackageName();
            	if (pkgName.length() > 0 && !packageNames.contains(pkgName))
            	{
            		packageNames.add(pkgName);
            		String[] parts = pkgName.split("\\.");
            		String current = "";
            		boolean firstOne = true;
            		for (String part : parts)
            		{
            			current += part;
            			if (partNames.contains(current))
            			{
            				firstOne = false;
        	                current += ".";
            				continue;
            			}            			
            			partNames.add(current);
        				sb.append("/**\n * @suppress {duplicate}\n * @const\n */\n");
            			if (firstOne)
            			{
            				sb.append("var ");
            				firstOne = false;
            			}
            			sb.append(current);
            			sb.append(" = {}");
            			sb.append(ASEmitterTokens.SEMICOLON.getToken() + "\n");
    	                current += ".";
            		}
            	}
            	sb.append("\n\n");
            	sb.append("/**\n");
            	sb.append(" * @interface\n");
            	String[] ifaces = cdef.getExtendedInterfacesAsDisplayStrings();
            	for (String iface : ifaces)
            		sb.append(" * @extends {" + iface + "}\n");
            	sb.append(" */\n");
                sb.append(cdef.getQualifiedName() + " = function() {}\n");
            }
        }
        if (config.isVerbose())
        {
            System.out.println("Writing externs report: " + externsReportFile.getAbsolutePath());
        }
        FileWriter fw;
		try {
			fw = new FileWriter(externsReportFile, false);
            fw.write(sb.toString());
            fw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}