| /* |
| * |
| * 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; |
| } |
| emitExports = emitExports && !node.hasModifier(ASModifier.STATIC) && !node.getFunctionClassification().equals(FunctionClassification.PACKAGE_MEMBER); |
| |
| 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 // 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 |
| { |
| 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; |
| } |
| |
| } |