/*
 *
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package org.apache.royale.compiler.internal.codegen.js.royale;

import java.util.*;

import org.apache.royale.compiler.asdoc.royale.ASDocComment;
import org.apache.royale.compiler.codegen.as.IASEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.common.ASModifier;
import org.apache.royale.compiler.common.DependencyType;
import org.apache.royale.compiler.constants.IASKeywordConstants;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.definitions.IClassDefinition;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.IFunctionDefinition;
import org.apache.royale.compiler.definitions.IFunctionDefinition.FunctionClassification;
import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.definitions.IVariableDefinition.VariableClassification;
import org.apache.royale.compiler.definitions.references.IReference;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSessionModel;
import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogDocEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.jx.BindableEmitter;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.scopes.ASScope;
import org.apache.royale.compiler.problems.PublicVarWarningProblem;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.*;
import org.apache.royale.compiler.tree.metadata.IMetaTagNode;
import org.apache.royale.compiler.tree.metadata.IMetaTagsNode;

public class JSRoyaleDocEmitter extends JSGoogDocEmitter
{
    private List<String> classIgnoreList;
    private List<String> ignoreList;
    private List<String> coercionList;
    private Map<String,List<String>> localSettings;
    public boolean emitStringConversions = true;
    private boolean emitExports = true;
    private boolean exportProtected = false;
    
    private boolean suppressClosure = false;

    public JSRoyaleDocEmitter(IJSEmitter emitter)
    {
        super(emitter);
    }

    public List<String> getClassIgnoreList()
    {
        return classIgnoreList;
    }
    
    public void setClassIgnoreList(List<String> value)
    {
        this.classIgnoreList = value;
    }
    
    public Boolean getSuppressClosure() {
        return suppressClosure;
    }
    
    public Boolean getEmitExports() {
        return emitExports;
    }

    @Override
    protected String convertASTypeToJS(String name, String pname)
    {
        if (ignoreList != null)
        {
            if (ignoreList.contains(pname + "." + name))
                return IASLanguageConstants.Object;
        }
        if (coercionList != null)
        {
            if (!coercionList.contains(pname + "." + name))
                return IASLanguageConstants.Object;
        }
        if (classIgnoreList != null)
        {
            if (classIgnoreList.contains(pname + "." + name))
                return IASLanguageConstants.Object;
        }
        if (name.matches("Vector\\.<.*>"))
        {
        	RoyaleJSProject fjp = (RoyaleJSProject)((IASEmitter)emitter).getWalker().getProject();
        	String vectorClassName = fjp.config == null ? null : fjp.config.getJsVectorEmulationClass();
        	if (vectorClassName != null) return vectorClassName;
        	return super.convertASTypeToJS(name, pname);
        }
        
        name = super.convertASTypeToJS(name, pname);
        if (name.equals(IASLanguageConstants.Boolean.toLowerCase())
                || name.equals(IASLanguageConstants.String.toLowerCase())
                || name.equals(IASLanguageConstants.Number.toLowerCase()))
            return name;

        return formatQualifiedName(name);
    }

    private boolean usedNames = false;
    
    @Override
    protected String formatQualifiedName(String name)
    {
    	return ((JSRoyaleEmitter)emitter).formatQualifiedName(name, !usedNames);
    }

    @Override
    public void emitMethodDoc(IFunctionNode node, ICompilerProject project)
    {
    	RoyaleJSProject fjp = (RoyaleJSProject)project;
        boolean keepASDoc = fjp.config != null && fjp.config.getKeepASDoc();
        boolean suppressExports = false;
        if (emitter instanceof JSRoyaleEmitter) {
            suppressExports = ((JSRoyaleEmitter) emitter).getModel().suppressExports;
        }
        if (fjp.config != null)
        {
        	emitExports = !suppressExports && fjp.config.getExportPublicSymbols();
        	exportProtected = !suppressExports && fjp.config.getExportProtectedSymbols();
        }
        else
        {
            emitExports = !suppressExports;
            exportProtected = false;
        }
        if (node.getAncestorOfType(IClassNode.class) != null)
        {
            // export custom namespaces (for now), but not public on a class
            emitExports = emitExports && !IASKeywordConstants.PUBLIC.equals(node.getNamespace());
        }
        else
        {
            // don't export public methods on an interface or a package-level function
            emitExports = false;
        }
        
        coercionList = null;
        ignoreList = null;
        localSettings = null;
        emitStringConversions = true;
        suppressClosure = false;

        IClassDefinition classDefinition = resolveClassDefinition(node);

        ASDocComment asDoc = (ASDocComment) node.getASDocComment();

        if (node instanceof IFunctionNode)
        {
            boolean hasDoc = false;
            Boolean override = false;
            
            if (node.isConstructor())
            {
                if (asDoc != null && keepASDoc)
                    write(changeAnnotations(asDoc.commentNoEnd()));
                else
                    begin();
                hasDoc = true;

                emitJSDocLine(JSEmitterTokens.CONSTRUCTOR);

                IClassDefinition parent = (IClassDefinition) node
                        .getDefinition().getParent();
                IClassDefinition superClass = parent.resolveBaseClass(project);
                String qname = (superClass != null) ? project.getActualPackageName(superClass.getQualifiedName()) : null;

                //support implicit bindable implementation for 'Extends' EventDispatcher:
                if (superClass == null || qname.equals(IASLanguageConstants.Object)) {
                    if (((JSRoyaleEmitter)emitter).getModel().getImplicitBindableImplementation()
                            == JSSessionModel.ImplicitBindableImplementation.EXTENDS) {
                        superClass = (IClassDefinition) project.resolveQNameToDefinition(BindableEmitter.DISPATCHER_CLASS_QNAME);
                        if (superClass == null) {
                            System.out.println(BindableEmitter.DISPATCHER_CLASS_QNAME+" not resolved for implicit super class in "+classDefinition.getQualifiedName());
                        } else qname = BindableEmitter.DISPATCHER_CLASS_QNAME;
                    }
                }

                usedNames = true;
                
                if (superClass != null
                        && !qname.equals(IASLanguageConstants.Object))
                    emitExtends(superClass, superClass.getPackageName());

                IReference[] references = classDefinition
                        .getImplementedInterfaceReferences();

                Boolean sawIEventDispatcher = false;
                Boolean needsIEventDispatcher = ((JSRoyaleEmitter)emitter).getModel().getImplicitBindableImplementation()
                                                == JSSessionModel.ImplicitBindableImplementation.IMPLEMENTS;

                for (IReference iReference : references)
                {
                    ITypeDefinition type = (ITypeDefinition) iReference
                            .resolve(project, (ASScope) classDefinition
                                    .getContainingScope(),
                                    DependencyType.INHERITANCE, true);
                    if (type == null) {
                        System.out.println(iReference.getDisplayString()
                                + " not resolved in "
                                + classDefinition.getQualifiedName());
                    } else {
                        emitImplements(type, project.getActualPackageName(type.getPackageName()));
                    }
                    if (type.getQualifiedName() == BindableEmitter.DISPATCHER_INTERFACE_QNAME)
                        sawIEventDispatcher=true;
                }
                //support implicit bindable implementation for 'implements' IEventDispatcher:
                if (needsIEventDispatcher && !sawIEventDispatcher) {
                    ITypeDefinition type = (ITypeDefinition) project.resolveQNameToDefinition(BindableEmitter.DISPATCHER_INTERFACE_QNAME);
                    if (type == null) {
                        System.out.println(BindableEmitter.DISPATCHER_INTERFACE_QNAME+" not resolved for implicit implementation in "+classDefinition.getQualifiedName());
                    } else {
                        emitImplements(type, project.getActualPackageName(type.getPackageName()));
                    }
                }
                usedNames = false;
            }
            else
            {
                // @override
                override = node.hasModifier(ASModifier.OVERRIDE);

                String ns = node.getNamespace();
                if (ns != null)
                {
                    if (asDoc != null && keepASDoc)
                    {
                        String docText = asDoc.commentNoEnd();
                        String keepToken = JSRoyaleEmitterTokens.EMIT_COERCION
                                .getToken();
                        if (docText.contains(keepToken))
                            loadKeepers(docText);
                        String ignoreToken = JSRoyaleEmitterTokens.IGNORE_COERCION
                        		.getToken();
		                if (docText.contains(ignoreToken))
		                    loadIgnores(docText);
                        String noStringToken = JSRoyaleEmitterTokens.IGNORE_STRING_COERCION
                        		.getToken();
		                if (docText.contains(noStringToken))
		                    emitStringConversions = false;
    
                        String noImplicitComplexCoercion = JSRoyaleEmitterTokens.SUPPRESS_COMPLEX_IMPLICIT_COERCION
                                .getToken();
                        if (docText.contains(noImplicitComplexCoercion))
                            loadLocalSettings(docText, noImplicitComplexCoercion, "true");
		                
                        String noResolveUncertain = JSRoyaleEmitterTokens.SUPPRESS_RESOLVE_UNCERTAIN
                                .getToken();
                        if (docText.contains(noResolveUncertain))
                            loadLocalSettings(docText,noResolveUncertain, "true");
		                
                        String suppressVectorIndexCheck = JSRoyaleEmitterTokens.SUPPRESS_VECTOR_INDEX_CHECK
                                .getToken();
                        if (docText.contains(suppressVectorIndexCheck))
                            loadLocalSettings(docText,suppressVectorIndexCheck, "true");
                        
                        String suppressClosureToken = JSRoyaleEmitterTokens.SUPPRESS_CLOSURE.getToken();
    
                        if (docText.contains(suppressClosureToken))
                            suppressClosure = true;
                        
                        String suppressExport = JSRoyaleEmitterTokens.SUPPRESS_EXPORT.getToken();
                        if (docText.contains(suppressExport)) {
                            emitExports = false;
                            if (IASKeywordConstants.PUBLIC.equals(ns)) // suppress it for reflection data checks:
                                ((JSRoyaleEmitter) (emitter)).getModel().suppressedExportNodes.add(node);
                        }
                        
                        write(changeAnnotations(asDoc.commentNoEnd()));
                    }
                    else
                        begin();
                    emitMethodAccess(node);
                    emitMethodNoCollapse(node, fjp);
                    hasDoc = true;
                }
            }

            if (!override)
            {
	            // @param
	            IParameterNode[] parameters = node.getParameterNodes();
	            for (IParameterNode pnode : parameters)
	            {
	                if (!hasDoc)
	                {
	                    if (asDoc != null && keepASDoc)
	                        write(changeAnnotations(asDoc.commentNoEnd()));
	                    else
	                        begin();
	                    emitMethodAccess(node);
                        emitMethodNoCollapse(node, fjp);
	                    hasDoc = true;
	                }
	
	                IExpressionNode enode = pnode.getNameExpressionNode();
	
	                ITypeDefinition tdef = enode.resolveType(project);
	                if (tdef == null)
	                    continue;
	
	                emitParam(pnode, project.getActualPackageName(tdef.getPackageName()));
	            }
            }
            
            if (!node.isConstructor())
            {
            	if (!override)
            	{
	                // @return
	                String returnType = node.getReturnType();
	                if (returnType != ""
	                        && returnType != ASEmitterTokens.VOID.getToken())
	                {
	                    if (!hasDoc)
	                    {
	                        if (asDoc != null && keepASDoc)
	                            write(changeAnnotations(asDoc.commentNoEnd()));
	                        else
	                            begin();
	                        emitMethodAccess(node);
                            emitMethodNoCollapse(node, fjp);
	                        hasDoc = true;
	                    }
	
	                    ITypeDefinition tdef = ((IFunctionDefinition) node
	                            .getDefinition()).resolveReturnType(project);
	
	                    String packageName = "";
	                    packageName = tdef != null ? tdef.getPackageName() : "";
	
	                    emitReturn(node, project.getActualPackageName(packageName));
	                }
            	}
            	
                if (override)
                {
                    if (!hasDoc)
                    {
                        if (asDoc != null && keepASDoc)
                            write(changeAnnotations(asDoc.commentNoEnd()));
                        else
                            begin();
                        emitMethodAccess(node);
                        emitMethodNoCollapse(node, fjp);
                        hasDoc = true;
                    }

                    emitOverride(node);
                }
            }

            if (hasDoc)
                end();
        }
    }
    
    private void loadLocalSettings(String doc, String settingToken, String defaultSetting)
    {
        if (localSettings == null) localSettings = new HashMap<String, List<String>>();
        int index = doc.indexOf(settingToken);
        List<String> settings = localSettings.containsKey(settingToken) ? localSettings.get(settingToken) : null;
        while (index != -1)
        {
            String setting = doc.substring(index + settingToken.length());
            int endIndex = setting.indexOf("\n");
            setting = setting.substring(0, endIndex);
            setting = setting.trim();
            if (settings == null) {
                settings = new ArrayList<String>();
                localSettings.put(settingToken, settings);
            }
            List<String> settingItems = null;
            if (setting.length() >0) {
                settingItems = Arrays.asList(setting.split("\\s*(,\\s*)+"));
            } else {
                settingItems =  Arrays.asList(defaultSetting);
            }
            for (String settingItem: settingItems) {
                if (settings.contains(settingItem)) {
                    //change the order to reflect the latest addition
                    settings.remove(settingItem);
                }
                settings.add(settingItem);
                //System.out.println("---Adding setting "+settingToken+":"+settingItem);
            }
            index = doc.indexOf(settingToken, index +  settingToken.length());
        }
    }
    
    public boolean hasLocalSetting(String settingToken) {
        if (localSettings == null) return false;
        return (localSettings.keySet().contains(settingToken));
    }
    
    public boolean getLocalSettingAsBoolean(JSRoyaleEmitterTokens token, Boolean defaultValue) {
        return getLocalSettingAsBoolean(token.getToken(), defaultValue);
    }
    
    public boolean getLocalSettingAsBoolean(String settingToken, Boolean defaultValue) {
        boolean setting = defaultValue;
        if (hasLocalSetting(settingToken)) {
            for (String stringVal: localSettings.get(settingToken)) {
                //don't bail out after finding a boolean-ish string val
                //'last one wins'
                if (stringVal.equals("false")) setting = false;
                else if (stringVal.equals("true")) setting = true;
            }
        }
        return setting;
    }
    
    public boolean getLocalSettingIncludesString(JSRoyaleEmitterTokens token, String searchValue) {
        return getLocalSettingIncludesString(token.getToken(), searchValue);
    }
    
    public boolean getLocalSettingIncludesString(String settingToken, String searchValue) {
        boolean hasValue = false;
        if (hasLocalSetting(settingToken)) {
            for (String stringVal: localSettings.get(settingToken)) {
                if (stringVal.equals(searchValue)) {
                    hasValue = true;
                    break;
                }
            }
        }
        return hasValue;
    }

    private void loadIgnores(String doc)
    {
    	ignoreList = new ArrayList<String>();
        String ignoreToken = JSRoyaleEmitterTokens.IGNORE_COERCION.getToken();
        int index = doc.indexOf(ignoreToken);
        while (index != -1)
        {
            String ignore = doc.substring(index + ignoreToken.length());
            int endIndex = ignore.indexOf("\n");
            ignore = ignore.substring(0, endIndex);
            ignore = ignore.trim();
            ignoreList.add(ignore);
            index = doc.indexOf(ignoreToken, index + endIndex);
        }
    }
    
    public boolean hasIgnore(String qName) {
        return ignoreList !=null && qName != null && ignoreList.contains(qName);
    }
    
    private void loadKeepers(String doc)
    {
    	coercionList = new ArrayList<String>();
        String keepToken = JSRoyaleEmitterTokens.EMIT_COERCION.getToken();
        int index = doc.indexOf(keepToken);
        while (index != -1)
        {
            String keeper = doc.substring(index + keepToken.length());
            int endIndex = keeper.indexOf("\n");
            keeper = keeper.substring(0, endIndex);
            keeper = keeper.trim();
            coercionList.add(keeper);
            index = doc.indexOf(keepToken, index + endIndex);
        }
    }

    private String changeAnnotations(String doc)
    {
        // rename these tags so they don't conflict with generated
        // jsdoc tags
        String pass1 = doc.replaceAll("@param", "@asparam");
        String pass2 = pass1.replaceAll("@return", "@asreturn");
        String pass3 = pass2.replaceAll("@private", "@asprivate");
        return pass3;
    }

    public void emitInterfaceMemberDoc(IDefinitionNode node,
            ICompilerProject project)
    {
    	RoyaleJSProject fjp =  (RoyaleJSProject)project;
        boolean keepASDoc = fjp.config != null && fjp.config.getKeepASDoc();
        boolean hasDoc = false;

        ASDocComment asDoc = (ASDocComment) ((IFunctionNode) node)
                .getASDocComment();

        String returnType = ((IFunctionNode) node).getReturnType();
        if (returnType != "" && returnType != ASEmitterTokens.VOID.getToken()) // has return
        {
            if (asDoc != null && keepASDoc)
                write(changeAnnotations(asDoc.commentNoEnd()));
            else
                begin();
            hasDoc = true;

            ITypeDefinition tdef = ((IFunctionDefinition) node.getDefinition())
                    .resolveReturnType(project);

            emitReturn((IFunctionNode) node, tdef.getPackageName());
        }

        IParameterNode[] parameters = ((IFunctionNode) node)
                .getParameterNodes();
        for (IParameterNode pnode : parameters)
        {
            if (!hasDoc)
            {
                if (asDoc != null && keepASDoc)
                    write(changeAnnotations(asDoc.commentNoEnd()));
                else
                    begin();
                hasDoc = true;
            }

            IExpressionNode enode = pnode.getNameExpressionNode();
            emitParam(pnode, enode.resolveType(project).getPackageName());
        }

        if (hasDoc)
            end();
    }

    @Override
    public void emitMethodAccess(IFunctionNode node)
    {
        String ns = node.getNamespace();
        if (ns == IASKeywordConstants.PRIVATE)
        {
            emitPrivate(node);
        }
        else if (ns == IASKeywordConstants.PROTECTED)
        {
            emitProtected(node);
        }
        else if (ns == IASKeywordConstants.INTERNAL)
        {
            emitInternal(node);
        }
        else // public or custom namespace
        {
            emitPublic(node);
        }
    }

    protected void emitMethodNoCollapse(IFunctionNode node, RoyaleJSProject fjp)
    {
        String ns = node.getNamespace();
        if (ns == IASKeywordConstants.PROTECTED)
        {
            boolean preventRenameProtected = fjp.config != null && fjp.config.getPreventRenameProtectedSymbols();
            if (preventRenameProtected)
            {
                emitNoCollapse(node);
            }
        }
        else if(ns != IASKeywordConstants.PRIVATE) // public or custom namespace
        {
            boolean preventRenamePublic = fjp.config != null && fjp.config.getPreventRenamePublicSymbols();
            if (preventRenamePublic)
            {
                emitNoCollapse(node);
            }
        }
    }

    protected void emitNoCollapse(IDefinitionNode node)
    {
        if (!node.hasModifier(ASModifier.STATIC)
                || node instanceof IAccessorNode
                || IASKeywordConstants.PRIVATE.equals(node.getNamespace()))
        {
            return;
        }
        //dynamically getting/setting a static field won't
        //work properly if it is collapsed in a release build,
        //even when it has been exported
        emitJSDocLine(JSGoogDocEmitterTokens.NOCOLLAPSE);
    }

    @Override
    public void emitFieldDoc(IVariableNode node, IDefinition def, ICompilerProject project)
    {
        RoyaleJSProject fjp =  (RoyaleJSProject)project;
        boolean suppressExports = false;
        if (emitter instanceof JSRoyaleEmitter) {
            suppressExports = ((JSRoyaleEmitter) emitter).getModel().suppressExports;
        }
        if (fjp.config != null)
        {
        	emitExports = !suppressExports && fjp.config.getExportPublicSymbols();
        	exportProtected = !suppressExports && fjp.config.getExportProtectedSymbols();
        }
        else
        {
            emitExports = !suppressExports;
            exportProtected = false;
        }
        emitExports = emitExports && !node.getVariableClassification().equals(VariableClassification.PACKAGE_MEMBER);

        begin();

        String ns = node.getNamespace();
        if (ns == IASKeywordConstants.PRIVATE)
        {
            emitPrivate(node);
        }
        else if (ns == IASKeywordConstants.PROTECTED)
        {
            emitProtected(node);
            boolean preventRename = fjp.config != null && fjp.config.getPreventRenameProtectedSymbols();
            if (preventRename)
            {
                emitNoCollapse(node);
            }
        }
        else if (ns == IASKeywordConstants.INTERNAL)
        {
            emitInternal(node);
        }
        else
        {
            boolean warnPublicVars = fjp.config != null && fjp.config.getWarnPublicVars() && !fjp.config.getPreventRenamePublicSymbols();
            IMetaTagsNode meta = node.getMetaTags();
            boolean bindable = false;
            if (meta != null)
            {
            	IMetaTagNode tag = meta.getTagByName("Bindable");
            	if (tag != null)
            		bindable = true;
            }
            if (warnPublicVars && !node.isConst() && !bindable && ns.contentEquals("public"))
            {
                IASNode warningNode = node;
                //find "public" child node, which may not be the start of the IVariableNode node because of associated metadata
                int childCount = node.getChildCount();
                int index = 0;
                while (index < childCount) {
                    IASNode child = node.getChild(index);
                    if (child instanceof IIdentifierNode && ((IIdentifierNode) child).getName().equals("public")) {
                        warningNode = child;
                        break;
                    }
                    index++;
                }
                
                if (!suppressedWarning(node, fjp))
                	fjp.getProblems().add(new PublicVarWarningProblem(node.getSourcePath(),
                            node.getStart(), node.getEnd(),
                            warningNode.getLine(), warningNode.getColumn(),
                            node.getEndLine(), node.getEndColumn()));
               

            }
            boolean avoidExport = (node.getASDocComment() instanceof ASDocComment
                    && ((ASDocComment)node.getASDocComment()).commentNoEnd()
                    .contains(JSRoyaleEmitterTokens.SUPPRESS_EXPORT.getToken()));
            
            if (!avoidExport) {
                if (ns.equals(IASKeywordConstants.PUBLIC))
                {
                    emitPublic(node);
                    boolean preventRename = fjp.config != null && fjp.config.getPreventRenamePublicSymbols();
                    if(preventRename)
                    {
                        emitNoCollapse(node);
                    }
                }
            } else {
                //we should also remove it from reflection data... provide a check here for that.
                ((JSRoyaleEmitter)emitter).getModel().suppressedExportNodes.add(node);
            }
        }

        if (node.isConst())
            emitConst(node);

        String packageName = "";
        if (def != null)
            packageName = def.getPackageName();

        emitType(node, project.getActualPackageName(packageName), project);

        end();
    }

    @Override
    public void emitProtected(IASNode node)
    {
    	if (exportProtected)
    		super.emitPublic(node);
    	else
    		super.emitProtected(node);
    }
    
    @Override
    public void emitPublic(IASNode node)
    {
    	if (emitExports)
    		super.emitPublic(node);
    }
    
    private boolean suppressedWarning(IVariableNode node, RoyaleJSProject fjp)
    {
        ASDocComment asDoc = (ASDocComment) node.getASDocComment();
        boolean keepASDoc = fjp.config != null && fjp.config.getKeepASDoc();
        String suppressToken = JSRoyaleEmitterTokens.SUPPRESS_PUBLIC_VAR_WARNING
        .getToken();
        if (asDoc != null && keepASDoc)
        {
            String docText = asDoc.commentNoEnd();
            if (docText.contains(suppressToken))
                return true;
        }
    	IASNode classNode = node.getParent().getParent();
    	if (classNode == null)
    		return false;
    	if (classNode.getNodeID() == ASTNodeID.ClassID)
    	{
    		asDoc = (ASDocComment) ((IClassNode)classNode).getASDocComment();
            if (asDoc != null && keepASDoc)
            {
                String docText = asDoc.commentNoEnd();
                if (docText.contains(suppressToken))
                    return true;
            }
            IClassDefinition cdef = ((IClassNode)classNode).getDefinition();
            if (cdef.isBindable())
            	return true;
            if (!cdef.isPublic())
            	return true;
    	}
    	return false;
    }

}
