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; } }