package com.intellij.lang.javascript.flex.importer;
import com.intellij.lang.javascript.dialects.ECMAL4LanguageDialect;
import com.intellij.lang.javascript.JSFlexAdapter;
import com.intellij.lang.javascript.JSTokenTypes;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.tree.IElementType;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Set;
/**
* @author Maxim.Mossienko
* Date: Oct 20, 2008
* Time: 7:02:29 PM
*/
class AS3InterfaceDumper extends AbstractDumpProcessor {
private int memberCount;
private boolean isInterface;
private boolean myDumpTypeRef;
public void dumpStat(@NotNull final String stat) {}
public void dumpToplevelAnonymousMethod(final @NotNull Abc abc, final @NotNull MethodInfo m) {}
public void dumpTopLevelTraits(final Abc abc, final @NotNull Traits t, final String indent) {
t.dump(abc, indent, "", this);
}
private static Lexer ourLexer = new JSFlexAdapter(ECMAL4LanguageDialect.DIALECT_OPTION_HOLDER);
public boolean doDumpMember(final @NotNull MemberInfo memberInfo) {
if (memberInfo.name == null) return false;
if (memberInfo.name.name != null) {
if(memberInfo.name.name.indexOf(Abc.$CINIT) >= 0) return false;
if (!StringUtil.isJavaIdentifier(memberInfo.name.name)) return false;
if (!JSTokenTypes.IDENTIFIER_TOKENS_SET.contains(identifierType(memberInfo.name.name)) ) {
return false;
}
if (isInterface) {
return memberInfo.parentTraits.init != memberInfo;
}
}
return true;
}
public static synchronized IElementType identifierType(String name) {
ourLexer.start(name);
if (ourLexer.getTokenEnd() != name.length()) {
return null;
}
return ourLexer.getTokenType();
}
public void appendMethodSeparator() {
append((++memberCount % 5) == 0? "\n":"");
}
public void appendFieldSeparator() {
appendMethodSeparator();
}
public String getAbcInSwfIndent() {
return "";
}
public void processValue(final Multiname typeName, final Object valueObject) {
append(" = ");
append(getValueRepr(valueObject));
}
protected static String getValueRepr(Object valueObject) {
if (valueObject == null) return null;
@NonNls String value = valueObject.toString();
char ch;
if (needsQuoting(value)) {
boolean doQoute = true;
if(value.indexOf('.') != -1) {
try {
Double.parseDouble(value);
doQoute=false;
} catch (NumberFormatException ex) {}
} else if (value.length() > 0 && (Character.isDigit(ch = value.charAt(0)) || (ch == '-' && value.length() > 1 && Character.isDigit(value.charAt(1))))) {
try {
Integer.parseInt(value);
doQoute=false;
} catch (NumberFormatException ex) {}
}
if (doQoute) {
value = "\"" + quote(value) + "\"";
}
}
return value;
}
private static @NonNls final Set<String> doNotNeedQoting =
new THashSet<>(Arrays.asList("null", "NaN", "undefined", "true", "false", "Infinity", "-Infinity"));
private static boolean needsQuoting(final String value) {
return !doNotNeedQoting.contains(value);
}
public boolean doDumpMetaData(final @NotNull MetaData md) {
return md.name.indexOf("__") == -1;
}
public void processParameter(@NotNull String name, @Nullable Multiname type, String parentName, @Nullable Multiname value, boolean rest) {
if (rest) {
append("... ");
append(name);
}
else {
append(name);
append(":");
dumpTypeRef(type, parentName, true);
if (value != null) {
processValue(type, value);
}
}
}
@Override
protected void dumpTypeRef(Multiname name, String parentName, boolean referenceNameRequested) {
myDumpTypeRef = true;
super.dumpTypeRef(name, parentName,referenceNameRequested);
myDumpTypeRef = false;
}
public boolean doStarTypeDumpInExtends() {
return false;
}
public boolean doStarMetaAttrNameDump() {
return false;
}
public void setProcessingInterface(final boolean anInterface) {
isInterface = anInterface;
}
public void hasError(@NotNull final String error) {
sb.append("/*" + error + "*/");
}
public void processMultinameAsPackageName(Multiname name, String parentName) {
append(getMultinameAsPackageName(name, parentName));
}
protected String getTypeRef(Multiname name, String parentName) {
try {
myDumpTypeRef = true;
return getMultinameAsPackageName(name, parentName);
} finally {
myDumpTypeRef = false;
}
}
protected String getMultinameAsPackageName(Multiname name, String parentName) {
if (name.nsset == null || (name.nsset.length == 1 && name.nsset[0].equals(Abc.PUBLIC_NS))) {
return name.name;
}
else {
final String validNsName = name.getValidNsName(classNameTable);
final int prefLength = "::".length();
if (Multiname.hasNamespace(validNsName) ||
(parentName != null && //parentName.equals(validNsName + "::" + name.name);
parentName.regionMatches(0, validNsName, 0, validNsName.length()) &&
parentName.regionMatches(validNsName.length(), "::", 0, prefLength) &&
parentName.regionMatches(validNsName.length() + prefLength, name.name, 0, name.name.length()) &&
parentName.length() == validNsName.length() + prefLength + name.name.length())
) {
return name.name;
}
if (parentName != null &&
!myDumpTypeRef &&
willDumpNsName(name, parentName, false, false, isTopLevelObject(parentName), validNsName)) {
return name.name;
}
return validNsName + "." + name.name;
}
}
protected String appendModifiers(MemberInfo member, String attr) {
@NonNls String s = attr;
s += "native ";
String nsName = member.name.getNsName(member);
if (nsName != null && nsName.length() > 0) s += nsName + " ";
if (member.isFinal) s+= "final ";
if (member.isOverride) s+= "override ";
return s;
}
private static boolean isTopLevelObject(String parentName) {
return parentName != null ? parentName.startsWith("script"):false;
}
private static boolean willDumpNsName(Multiname name, String parentName, boolean memberInParentNs, boolean constructor, boolean topLevelObject, String nsName) {
return name != null && name.hasNotEmptyNs() && parentName != null &&
((!constructor && !topLevelObject && !memberInParentNs) || nsName.indexOf("private") != -1);
}
@Override
public void processFunction(MethodInfo methodInfo, boolean referenceNameRequested, Abc abc, String indent, String attr) {
super.processFunction(methodInfo, referenceNameRequested, abc, indent, attr);
append(";\n");
}
@Override
public void processVariable(SlotInfo info, String indent, String attr) {
super.processVariable(info, indent, attr);
append(";\n");
}
protected boolean dumpRestParameter() {
return true;
}
}