package jetbrains.mps.baseLanguage.javastub;
/*Generated by MPS */
import jetbrains.mps.vfs.IFile;
import org.jetbrains.org.objectweb.asm.ClassReader;
import org.jetbrains.org.objectweb.asm.tree.InnerClassNode;
import org.jetbrains.mps.openapi.model.SNodeId;
import org.jetbrains.mps.openapi.model.SNode;
import jetbrains.mps.stubs.javastub.classpath.ClassifierKind;
import jetbrains.mps.util.NameUtil;
import jetbrains.mps.smodel.LazySNode;
import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SPropertyOperations;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations;
import org.jetbrains.org.objectweb.asm.Opcodes;
import jetbrains.mps.lang.smodel.generator.smodelAdapter.SLinkOperations;
import jetbrains.mps.baseLanguage.javastub.asm.ASMClass;
import java.util.List;
import java.util.ArrayList;
import jetbrains.mps.java.stub.ReferenceFactory;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.io.InputStream;
import jetbrains.mps.util.ReadUtil;
import java.io.IOException;
import org.jetbrains.mps.openapi.persistence.PersistenceFacade;
import jetbrains.mps.smodel.SModelUtil_new;
public class ClassifierLoader {
private final boolean mySkipPrivate;
private final boolean myOnlyPublic;
private final IFile myFile;
private final ClassReader myClassReader;
private InnerClassNode myInnerClassDescriptor;
public ClassifierLoader(IFile file, boolean onlyPublic, boolean skipPrivate) {
mySkipPrivate = skipPrivate;
myOnlyPublic = onlyPublic;
myFile = file;
byte[] code = readClass(file);
myClassReader = (code == null ? null : new ClassReader(code));
}
private ClassifierLoader(IFile file, ClassifierLoader outer, InnerClassNode innerClassStruct) {
this(file, outer.myOnlyPublic, outer.mySkipPrivate);
myInnerClassDescriptor = innerClassStruct;
}
public SNodeId createNodeId() {
return ASMNodeId.createId(getClassName(myFile));
}
public SNode createClassifier() {
if (myClassReader == null) {
return null;
}
if (isIgnored()) {
return null;
}
final ClassifierKind kind = ClassifierKind.getClassifierKind(myClassReader);
final String className = getClassName(myFile);
final SNodeId nodeId = ASMNodeId.createId(className);
final String shortName = NameUtil.shortNameFromLongName(className.replace('$', '.'));
SNode lazyRoot;
switch (kind) {
case CLASS:
lazyRoot = new LazySNode(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, "jetbrains.mps.baseLanguage.structure.ClassConcept"), nodeId);
SPropertyOperations.set(SNodeOperations.cast(lazyRoot, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, "jetbrains.mps.baseLanguage.structure.ClassConcept")), MetaAdapterFactory.getProperty(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, 0xfa5cee6dfaL, "abstractClass"), "" + ((myClassReader.getAccess() & Opcodes.ACC_ABSTRACT) != 0));
SPropertyOperations.set(SNodeOperations.cast(lazyRoot, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, "jetbrains.mps.baseLanguage.structure.ClassConcept")), MetaAdapterFactory.getProperty(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xf8c108ca66L, 0x11c6af4b284L, "isFinal"), "" + ((myClassReader.getAccess() & Opcodes.ACC_FINAL) != 0));
break;
case INTERFACE:
lazyRoot = new LazySNode(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101edd46144L, "jetbrains.mps.baseLanguage.structure.Interface"), nodeId);
break;
case ENUM:
lazyRoot = new LazySNode(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0xfc367070a5L, "jetbrains.mps.baseLanguage.structure.EnumClass"), nodeId);
break;
case ANNOTATIONS:
lazyRoot = new LazySNode(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x114a69dc80cL, "jetbrains.mps.baseLanguage.structure.Annotation"), nodeId);
break;
default:
return null;
}
SNode rv = SNodeOperations.as(lazyRoot, MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, "jetbrains.mps.baseLanguage.structure.Classifier"));
SPropertyOperations.set(rv, MetaAdapterFactory.getProperty(0xceab519525ea4f22L, 0x9b92103b95ca8c0cL, 0x110396eaaa4L, 0x110396ec041L, "name"), shortName);
if (myInnerClassDescriptor != null) {
// static, protected, private are accessible from inner class structure only,
// JLS 4.7.6, table 4.8
boolean isStatic = (myInnerClassDescriptor.access & Opcodes.ACC_STATIC) != 0;
boolean isProtected = (myInnerClassDescriptor.access & Opcodes.ACC_PROTECTED) != 0;
boolean isPrivate = (myInnerClassDescriptor.access & Opcodes.ACC_PRIVATE) != 0;
// public, final, abstract are taken from the class, JLS 4.1, table 4.1
SPropertyOperations.set(rv, MetaAdapterFactory.getProperty(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, 0x73c6d8a8c021f99L, "nonStatic"), "" + (!(isStatic)));
if (isProtected) {
SLinkOperations.setTarget(rv, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x112670d273fL, 0x112670d886aL, "visibility"), createProtectedVisibility_eoyrbu_a0a0h0l0m());
} else if (isPrivate) {
SLinkOperations.setTarget(rv, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x112670d273fL, 0x112670d886aL, "visibility"), createPrivateVisibility_eoyrbu_a0a0a7a11a21());
}
}
return rv;
}
private Iterable<ClassifierLoader> getInnerClassifiers(ASMClass ac) {
List<InnerClassNode> innerClasses = ac.getInnerClasses();
String outerName = myClassReader.getClassName();
IFile parent = myFile.getParent();
ArrayList<ClassifierLoader> rv = new ArrayList<ClassifierLoader>();
for (InnerClassNode cn : innerClasses) {
String name = cn.name;
if (name == null) {
// I doubt this could ever happen
continue;
}
if (cn.innerName == null) {
// JVM spec, 4.7.6, inner_name_index - anonymous classes have no inner name
continue;
}
if ((cn.access & Opcodes.ACC_SYNTHETIC) != 0) {
continue;
}
boolean isPrivate = (cn.access & Opcodes.ACC_PRIVATE) != 0;
if (isPrivate && mySkipPrivate) {
continue;
}
if (!(outerName.equals(cn.outerName))) {
continue;
}
int index = name.lastIndexOf('/');
if (index != -1) {
name = name.substring(index + 1);
}
ClassifierLoader inner = new ClassifierLoader(parent.getDescendant(name + ".class"), this, cn);
rv.add(inner);
}
return rv;
}
public void updateClassifier(SNode classifier, ReferenceFactory refFactory) {
assert myClassReader != null;
ASMClass ac = new ASMClass(myClassReader, true);
new ClassifierUpdater(ac, mySkipPrivate, refFactory).update(classifier);
for (ClassifierLoader innerLoader : getInnerClassifiers(ac)) {
SNode inner = innerLoader.createClassifier();
if (inner != null) {
ListSequence.fromList(SLinkOperations.getChildren(classifier, MetaAdapterFactory.getContainmentLink(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x101d9d3ca30L, 0x4a9a46de59132803L, "member"))).addElement(inner);
innerLoader.updateClassifier(inner, refFactory);
}
}
}
private boolean isIgnored() {
return myOnlyPublic && (myClassReader.getAccess() & Opcodes.ACC_PUBLIC) == 0;
}
private static byte[] readClass(IFile file) {
try {
byte[] result = null;
InputStream inp = null;
try {
inp = file.openInputStream();
result = ReadUtil.read(inp);
} finally {
if (inp != null) {
inp.close();
}
}
return result;
} catch (IOException e) {
return null;
}
}
public static String getClassName(IFile file) {
String name = file.getName();
return name.substring(0, name.indexOf('.'));
}
private static SNode createProtectedVisibility_eoyrbu_a0a0h0l0m() {
PersistenceFacade facade = PersistenceFacade.getInstance();
SNode n1 = SModelUtil_new.instantiateConceptDeclaration(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x10af958b686L, "jetbrains.mps.baseLanguage.structure.ProtectedVisibility"), null, null, false);
return n1;
}
private static SNode createPrivateVisibility_eoyrbu_a0a0a7a11a21() {
PersistenceFacade facade = PersistenceFacade.getInstance();
SNode n1 = SModelUtil_new.instantiateConceptDeclaration(MetaAdapterFactory.getConcept(0xf3061a5392264cc5L, 0xa443f952ceaf5816L, 0x10af9586f0cL, "jetbrains.mps.baseLanguage.structure.PrivateVisibility"), null, null, false);
return n1;
}
}