/* * Copyright (C) 2010 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.wikbook.codesource; import japa.parser.ParseException; import japa.parser.ast.PackageDeclaration; import japa.parser.ast.body.AnnotationDeclaration; import japa.parser.ast.body.AnnotationMemberDeclaration; import japa.parser.ast.body.BodyDeclaration; import japa.parser.ast.body.ClassOrInterfaceDeclaration; import japa.parser.ast.body.ConstructorDeclaration; import japa.parser.ast.body.EnumDeclaration; import japa.parser.ast.body.FieldDeclaration; import japa.parser.ast.body.MethodDeclaration; import japa.parser.ast.body.TypeDeclaration; import japa.parser.ast.body.VariableDeclarator; import japa.parser.ast.body.VariableDeclaratorId; import japa.parser.ast.expr.NameExpr; import japa.parser.ast.expr.ObjectCreationExpr; import japa.parser.ast.expr.QualifiedNameExpr; import japa.parser.ast.visitor.GenericVisitorAdapter; import org.cojen.classfile.ClassFile; import org.cojen.classfile.MethodDesc; import org.cojen.classfile.MethodInfo; import org.cojen.classfile.TypeDesc; import org.wikbook.text.Clip; import org.wikbook.text.TextArea; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> * @version $Revision$ */ class CompilationUnitVisitor extends GenericVisitorAdapter<Void, Visit> { /** . */ private final CodeSourceBuilder builder; CompilationUnitVisitor(CodeSourceBuilder builder) { this.builder = builder; } Visit.CU visit(String compilationUnitPath) throws IOException, ParseException, CodeSourceException { InputStream cuis = builder.context.getResource(compilationUnitPath); // if (cuis == null) { throw new NoSuchSourceException("Compilation path cannot be located " + compilationUnitPath); } // ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[20]; for (int l = cuis.read(buffer); l != -1; l = cuis.read(buffer)) { baos.write(buffer, 0, l); } String s = baos.toString(); // Visit.CU visit = new Visit.CU(s); // visit.accept(this); // return visit; } private String toString(NameExpr n) { if (n instanceof QualifiedNameExpr) { QualifiedNameExpr qn = (QualifiedNameExpr)n; return qn.getQualifier() + "." + qn.getName(); } else { return n.getName(); } } @Override public Void visit(PackageDeclaration n, Visit arg) { ((Visit.CU)arg).pkg = toString(n.getName()); return super.visit(n, arg); } private static interface SuperVisit<T extends TypeDeclaration> { Void visit(T td, Visit v); } /** * @param declaration the declaration * @param visit the current visit * @param superVisit the callback for continuing the visit * @param <D> the declaration generic type * @return the void */ private <D extends TypeDeclaration> Void visit(D declaration, Visit.TD visit, SuperVisit<D> superVisit) { String pkg = visit.getPkg(); String fqn = visit.getFQN(); // Get path of the class String path = visit.getPath(); // InputStream in = builder.context.getResource(path); if (in == null) { throw new CodeSourceException("Cannot locate class file for fqn " + fqn + " with path " + path); } // try { ClassFile cf = ClassFile.readFrom(in); // List<Signature> constructorSignatures = new ArrayList<Signature>(); for (MethodInfo mi : cf.getConstructors()) { MethodDesc desc = mi.getMethodDescriptor(); List<String> parameterTypes = new ArrayList<String>(); for (TypeDesc typeDesc : desc.getParameterTypes()) { parameterTypes.add(typeDesc.getFullName()); } constructorSignatures.add(new Signature(parameterTypes)); } // List<Signature> methodSignatures = new ArrayList<Signature>(); for (MethodInfo mi : cf.getMethods()) { MethodDesc desc = mi.getMethodDescriptor(); List<String> parameterTypes = new ArrayList<String>(); for (TypeDesc typeDesc : desc.getParameterTypes()) { parameterTypes.add(typeDesc.getFullName()); } methodSignatures.add(new Signature(parameterTypes)); } // visit.constructorSignatures = constructorSignatures.iterator(); visit.methodSignatures = methodSignatures.iterator(); } catch (IOException e) { throw new CodeSourceException("Could not load class " + fqn, e); } // visit.stack.addLast(new LinkedList<CodeSource>()); // Void ret = superVisit.visit(declaration, visit); // List<CodeSource> blah = visit.stack.removeLast(); // Clip typeClip = Clip.get(declaration.getBeginLine() - 1, 0, declaration.getEndLine() - 1, declaration.getEndColumn()); // TypeSource typeSource = new TypeSource( new TextArea(visit.getCU().source), fqn, typeClip, visit.javaDoc(declaration)); // for (CodeSource source : blah) { MemberSource methodSource = (MemberSource)source; typeSource.addMember(methodSource); } // visit.getCU().types.add(typeSource); // return ret; } @Override public Void visit(ClassOrInterfaceDeclaration n, Visit v) { return visit(n, new Visit.TD(v, n), new SuperVisit<ClassOrInterfaceDeclaration>() { public Void visit(ClassOrInterfaceDeclaration td, Visit v) { return CompilationUnitVisitor.super.visit(td, v); } }); } @Override public Void visit(EnumDeclaration n, Visit v) { return visit(n, new Visit.TD(v, n), new SuperVisit<EnumDeclaration>() { public Void visit(EnumDeclaration td, Visit v) { return CompilationUnitVisitor.super.visit(td, v); } }); } @Override public Void visit(AnnotationDeclaration n, Visit v) { return visit(n, new Visit.TD(v, n), new SuperVisit<AnnotationDeclaration>() { public Void visit(AnnotationDeclaration td, Visit v) { return CompilationUnitVisitor.super.visit(td, v); } }); } private static Clip clip(BodyDeclaration body) { return Clip.get(body.getBeginLine() - 1, 0, body.getEndLine() - 1, body.getEndColumn()); } @Override public Void visit(FieldDeclaration n, Visit v) { if (n.getVariables().size() == 1) { VariableDeclarator declarator = n.getVariables().get(0); VariableDeclaratorId id = declarator.getId(); NamedMemberSource fieldSource = new NamedMemberSource( id.getName(), clip(n), v.javaDoc(n)); ((Visit.TD)v).stack.getLast().addLast(fieldSource); } else { throw new UnsupportedOperationException("todo"); } return super.visit(n, v); } @Override public Void visit(AnnotationMemberDeclaration n, Visit v) { SignedMemberSource memberSource = new SignedMemberSource( MemberKey.createSignedKey(n.getName()), clip(n), v.javaDoc(n)); // ((Visit.TD)v).stack.getLast().addLast(memberSource); return super.visit(n, v); } @Override public Void visit(ObjectCreationExpr n, Visit arg) { // We don't do anything here because we will not find any class // except anonymous inner classes but we want to avoid them // since their member will confuse the .java / .class matching return null; } @Override public Void visit(MethodDeclaration n, Visit v) { Iterator<Signature> signatures = ((Visit.TD)v).methodSignatures; if (!signatures.hasNext()) { throw new CodeSourceException("Did not find a method signature for declaration " + n.getName()); } // Signature signature = signatures.next(); // SignedMemberSource methodSource = new SignedMemberSource( new MemberKey(n.getName(), signature), clip(n), v.javaDoc(n)); // ((Visit.TD)v).stack.getLast().addLast(methodSource); return super.visit(n, v); } @Override public Void visit(ConstructorDeclaration n, Visit v) { Iterator<Signature> signatures = ((Visit.TD)v).constructorSignatures; if (!signatures.hasNext()) { throw new CodeSourceException("Did not find a constructor signature for declaration " + n.getName()); } // Signature signature = signatures.next(); // SignedMemberSource methodSource = new SignedMemberSource( new MemberKey(n.getName(), signature), clip(n), v.javaDoc(n)); // ((Visit.TD)v).stack.getLast().addLast(methodSource); return super.visit(n, v); } }