/** Construct a new compiler from a shared context. */
  public AptJavaCompiler(Context context) {
    super(preRegister(context));

    context.put(compilerKey, this);
    apt = Apt.instance(context);

    ClassReader classReader = ClassReader.instance(context);
    classReader.preferSource = true;

    // TEMPORARY NOTE: bark==log, but while refactoring, we maintain their
    // original identities, to remember the original intent.
    log = Log.instance(context);
    bark = Bark.instance(context);

    Options options = Options.instance(context);
    classOutput = options.get("-retrofit") == null;
    nocompile = options.get("-nocompile") != null;
    print = options.get("-print") != null;
    classesAsDecls = options.get("-XclassesAsDecls") != null;

    genSourceFileNames = new java.util.LinkedHashSet<String>();
    genClassFileNames = new java.util.LinkedHashSet<String>();

    // this forces a copy of the line map to be kept in the tree,
    // for use by com.sun.mirror.util.SourcePosition.
    lineDebugInfo = true;
  }
  @Override
  public void visitInnerClass(
      final String name, final String outerName, final String innerName, final int access) {
    if ((access & Opcodes.ACC_SYNTHETIC) != 0) return;
    if (!isCorrectName(innerName) || outerName == null) return;

    if ((getClassName(outerName) + "." + innerName).equals(myResult.getQualifiedName())) {
      // our result is inner class
      if (myParent instanceof PsiFileStub) {
        throw new OutOfOrderInnerClassException();
      }
    }

    if (!getClassName(outerName).equals(myResult.getQualifiedName())) return;

    final T innerSource = myInnersStrategy.findInnerClass(innerName, mySource);
    if (innerSource == null) return;

    final ClassReader reader = myInnersStrategy.readerForInnerClass(innerSource);
    if (reader == null) return;

    final StubBuildingVisitor<T> classVisitor =
        new StubBuildingVisitor<T>(innerSource, myInnersStrategy, myResult, access, innerName);
    reader.accept(classVisitor, ClassReader.SKIP_FRAMES);
  }
  @Override
  public void handle(StringBuilder line, TemplateReader tpl, Environment env, Appendable out)
      throws IOException {
    // get the class name
    String klass = getArgs(line);

    // read in the class
    ClassReader rdr = new ClassReader();
    while (true) {
      line = tpl.next();

      if (line == null || (isCodeLine(line) && getCmd(line).equals("endclass"))) break;

      rdr.add(line.toString());
    }

    // format and print objects!
    Environment oenv;
    int i = 0;
    for (TemplateObject o : env.getObjectsFor(klass)) {
      rdr.rewind();
      oenv = env.getEnvironmentFor(o);
      oenv.setValue("FIRST", (i == 0) ? "1" : null);
      oenv.setValue("NOTFIRST", (i != 0) ? "1" : null);
      oenv.setValue("INDEX", String.valueOf(i++));
      Template.doTemplateLoop(rdr, oenv, out);
    }
  }
Example #4
0
 private byte[] transformThreadPool(ThreadPoolCfg md, byte[] classfileBuffer) {
   ClassWriter w = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
   ClassVisitor a = new PoolClassAdapter(w, md);
   ClassReader r = new ClassReader(classfileBuffer);
   r.accept(a, ClassReader.EXPAND_FRAMES);
   return w.toByteArray();
 }
  @Override
  public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
      throws IOException {
    ClassReader cls = context.getClassSource().get(methodRef.getClassName());
    MethodReader method = cls.getMethod(methodRef.getDescriptor());
    AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName());

    AnnotationReader refAnnot = method.getAnnotations().get(MetadataProviderRef.class.getName());
    methodRef = MethodReference.parse(refAnnot.getValue("value").getString());

    // Find and instantiate metadata generator
    ValueType generatorType = providerAnnot.getValue("value").getJavaClass();
    String generatorClassName = ((ValueType.Object) generatorType).getClassName();
    Class<?> generatorClass;
    try {
      generatorClass = Class.forName(generatorClassName, true, context.getClassLoader());
    } catch (ClassNotFoundException e) {
      context
          .getDiagnostics()
          .error(
              new CallLocation(methodRef),
              "Can't find metadata provider class {{c0}}",
              generatorClassName);
      return;
    }
    Constructor<?> cons;
    try {
      cons = generatorClass.getConstructor();
    } catch (NoSuchMethodException e) {
      context
          .getDiagnostics()
          .error(
              new CallLocation(methodRef),
              "Metadata generator {{c0}} does not have " + "a public no-arg constructor",
              generatorClassName);
      return;
    }
    MetadataGenerator generator;
    try {
      generator = (MetadataGenerator) cons.newInstance();
    } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
      context
          .getDiagnostics()
          .error(
              new CallLocation(methodRef),
              "Error instantiating metadata " + "generator {{c0}}",
              generatorClassName);
      return;
    }
    DefaultMetadataGeneratorContext metadataContext =
        new DefaultMetadataGeneratorContext(
            context.getClassSource(), context.getClassLoader(), context.getProperties(), context);

    // Generate resource loader
    Resource resource = generator.generateMetadata(metadataContext, methodRef);
    writer.append("return ");
    ResourceWriterHelper.write(writer, resource);
    writer.append(';').softNewLine();
  }
Example #6
0
  @Override
  public void visitTopLevel(JCCompilationUnit tree) {
    JavaFileObject prev = log.useSource(tree.sourcefile);
    boolean addEnv = false;
    boolean isPkgInfo =
        tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE);
    if (tree.pid != null) {
      tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid));
      if (tree.packageAnnotations.nonEmpty() || pkginfoOpt == PkgInfo.ALWAYS) {
        if (isPkgInfo) {
          addEnv = true;
        } else {
          log.error(tree.packageAnnotations.head.pos(), "pkg.annotations.sb.in.package-info.java");
        }
      }
    } else {
      tree.packge = syms.unnamedPackage;
    }
    tree.packge.complete(); // Find all classes in package.
    Env<AttrContext> topEnv = topLevelEnv(tree);

    // Save environment of package-info.java file.
    if (isPkgInfo) {
      Env<AttrContext> env0 = typeEnvs.get(tree.packge);
      if (env0 == null) {
        typeEnvs.put(tree.packge, topEnv);
      } else {
        JCCompilationUnit tree0 = env0.toplevel;
        if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
          log.warning(
              tree.pid != null ? tree.pid.pos() : null, "pkg-info.already.seen", tree.packge);
          if (addEnv
              || (tree0.packageAnnotations.isEmpty()
                  && tree.docComments != null
                  && tree.docComments.get(tree) != null)) {
            typeEnvs.put(tree.packge, topEnv);
          }
        }
      }

      for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner) q.flags_field |= EXISTS;

      Name name = names.package_info;
      ClassSymbol c = reader.enterClass(name, tree.packge);
      c.flatname = names.fromString(tree.packge + "." + name);
      c.sourcefile = tree.sourcefile;
      c.completer = null;
      c.members_field = new Scope(c);
      tree.packge.package_info = c;
    }
    classEnter(tree.defs, topEnv);
    if (addEnv) {
      todo.append(topEnv);
    }
    log.useSource(prev);
    result = null;
  }
  protected void doTest(String path) throws Exception {
    File ktFile = new File(path);
    assertTrue("Cannot find a file " + ktFile.getAbsolutePath(), ktFile.exists());

    String fileText = FileUtil.loadFile(ktFile, true);

    KtFile psiFile =
        KotlinTestUtils.createFile(ktFile.getName(), fileText, jetCoreEnvironment.getProject());

    OutputFileCollection outputFiles =
        GenerationUtils.compileFileGetClassFileFactoryForTest(psiFile, jetCoreEnvironment);

    List<TestedObject> testedObjects = parseExpectedTestedObject(fileText);
    for (TestedObject testedObject : testedObjects) {
      String className = null;
      for (OutputFile outputFile : outputFiles.asList()) {
        String filePath = outputFile.getRelativePath();
        if (testedObject.isFullContainingClassName
            && filePath.equals(testedObject.containingClass + ".class")) {
          className = filePath;
        } else if (!testedObject.isFullContainingClassName
            && filePath.startsWith(testedObject.containingClass)) {
          className = filePath;
        }
      }

      assertNotNull(
          "Couldn't find a class file with name " + testedObject.containingClass, className);

      OutputFile outputFile = outputFiles.get(className);
      assertNotNull(outputFile);

      ClassReader cr = new ClassReader(outputFile.asByteArray());
      TestClassVisitor classVisitor = getClassVisitor(testedObject.kind, testedObject.name, false);
      cr.accept(classVisitor, ClassReader.SKIP_CODE);

      if (!classVisitor.isExists()) {
        classVisitor = getClassVisitor(testedObject.kind, testedObject.name, true);
        cr.accept(classVisitor, ClassReader.SKIP_CODE);
      }

      boolean isObjectExists =
          !Boolean.valueOf(findStringWithPrefixes(testedObject.textData, "// ABSENT: "));
      assertEquals(
          "Wrong object existence state: " + testedObject, isObjectExists, classVisitor.isExists());

      if (isObjectExists) {
        assertEquals(
            "Wrong access flag for " + testedObject + " \n" + outputFile.asText(),
            getExpectedFlags(testedObject.textData),
            classVisitor.getAccess());
      }
    }
  }
Example #8
0
  @Override
  public byte[] transform(String name, String transformedName, byte[] basicClass) {
    if (basicClass == null) return null;
    ClassReader reader = new ClassReader(basicClass);
    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);

    ClassVisitor visitor = writer;
    visitor = new ExitVisitor(visitor);

    reader.accept(visitor, 0);
    return writer.toByteArray();
  }
 RuntimeParameterAnnotations_attribute(ClassReader cr, int name_index, int length)
     throws IOException, Annotation.InvalidAnnotation {
   super(name_index, length);
   int num_parameters = cr.readUnsignedByte();
   parameter_annotations = new Annotation[num_parameters][];
   for (int p = 0; p < parameter_annotations.length; p++) {
     int num_annotations = cr.readUnsignedShort();
     Annotation[] annotations = new Annotation[num_annotations];
     for (int i = 0; i < num_annotations; i++) annotations[i] = new Annotation(cr);
     parameter_annotations[p] = annotations;
   }
 }
Example #10
0
 Code_attribute(ClassReader cr, int name_index, int length)
     throws IOException, ConstantPoolException {
   super(name_index, length);
   max_stack = cr.readUnsignedShort();
   max_locals = cr.readUnsignedShort();
   code_length = cr.readInt();
   code = new byte[code_length];
   cr.readFully(code);
   exception_table_langth = cr.readUnsignedShort();
   exception_table = new Exception_data[exception_table_langth];
   for (int i = 0; i < exception_table_langth; i++) exception_table[i] = new Exception_data(cr);
   attributes = new Attributes(cr);
 }
 public static Class<?> malform(Class<?> type) throws Exception {
   ClassReader classReader = new ClassReader(type.getName());
   ClassWriter classWriter = new ClassWriter(classReader, 0);
   classReader.accept(new SignatureMalformer(classWriter), 0);
   ClassLoader classLoader =
       new ByteArrayClassLoader(
           null,
           Collections.singletonMap(type.getName(), classWriter.toByteArray()),
           null,
           ByteArrayClassLoader.PersistenceHandler.MANIFEST,
           PackageDefinitionStrategy.NoOp.INSTANCE);
   return classLoader.loadClass(type.getName());
 }
  protected byte[] transformClass(byte[] bytes, String clssname) {
    InputStream is = getClass().getResourceAsStream("/" + clssname.replace('.', '/') + ".class");

    ClassReader orig = null;
    try {
      ClassReader crRepl = new ClassReader(is);
      ClassNode cnRepl = new ClassNode(Opcodes.ASM4);
      crRepl.accept(cnRepl, ClassReader.SKIP_FRAMES);

      ClassReader crOrig = new ClassReader(bytes);
      ClassNode cnOrig = new ClassNode(Opcodes.ASM4);
      crOrig.accept(cnOrig, ClassReader.SKIP_FRAMES);

      for (Object ofnRepl : cnRepl.fields) {
        FieldNode fnRepl = (FieldNode) ofnRepl;

        if (hasReplaceAnnotation(fnRepl.visibleAnnotations)) {
          FieldNode fnOrig = findField(cnOrig.fields, fnRepl);
          if (fnOrig != null) {
            cnOrig.fields.remove(fnOrig);
            cnOrig.fields.add(cnOrig.fields.size(), scrubField(cnOrig, cnRepl, fnRepl));
          }
        } else if (hasAddAnnotation(fnRepl.visibleAnnotations)) {
          cnOrig.fields.add(cnOrig.fields.size(), scrubField(cnOrig, cnRepl, fnRepl));
        }
      }

      for (Object omnRepl : cnRepl.methods) {
        MethodNode mnRepl = (MethodNode) omnRepl;

        if (hasReplaceAnnotation(mnRepl.visibleAnnotations)) {
          MethodNode mnOrig = findMethod(cnOrig.methods, mnRepl);
          if (mnOrig != null) {
            cnOrig.methods.remove(mnOrig);
            cnOrig.methods.add(cnOrig.methods.size(), scrubMethod(cnOrig, cnRepl, mnRepl));
          }
        } else if (hasAddAnnotation(mnRepl.visibleAnnotations)) {
          cnOrig.methods.add(cnOrig.methods.size() + 1, scrubMethod(cnOrig, cnRepl, mnRepl));
        }
      }

      ClassWriter cwNew = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
      cnOrig.accept(cwNew);
      return cwNew.toByteArray();
    } catch (IOException e) {
      e.printStackTrace(); // To change body of catch statement use File | Settings | File
      // Templates.
    }

    return bytes;
  }
Example #13
0
  private static void checkLeakingParameters(Class<?> jClass) throws IOException {
    final HashMap<Method, boolean[]> map = new HashMap<Method, boolean[]>();

    // collecting leakedParameters
    final ClassReader classReader =
        new ClassReader(
            new FileInputStream(
                jClass.getResource("/" + jClass.getName().replace('.', '/') + ".class").getFile()));
    classReader.accept(
        new ClassVisitor(Opcodes.ASM5) {
          @Override
          public MethodVisitor visitMethod(
              int access, String name, String desc, String signature, String[] exceptions) {
            final MethodNode node =
                new MethodNode(Opcodes.ASM5, access, name, desc, signature, exceptions);
            final Method method = new Method(classReader.getClassName(), name, desc);
            return new MethodVisitor(Opcodes.ASM5, node) {
              @Override
              public void visitEnd() {
                super.visitEnd();
                try {
                  map.put(
                      method,
                      LeakingParameters.build(classReader.getClassName(), node, false).parameters);
                } catch (AnalyzerException ignore) {
                }
              }
            };
          }
        },
        ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);

    for (java.lang.reflect.Method jMethod : jClass.getDeclaredMethods()) {
      Method method =
          new Method(
              Type.getType(jClass).getInternalName(),
              jMethod.getName(),
              Type.getMethodDescriptor(jMethod));
      Annotation[][] annotations = jMethod.getParameterAnnotations();
      for (int i = 0; i < annotations.length; i++) {
        boolean isLeaking = false;
        Annotation[] parameterAnnotations = annotations[i];
        for (Annotation parameterAnnotation : parameterAnnotations) {
          if (parameterAnnotation.annotationType() == ExpectLeaking.class) {
            isLeaking = true;
          }
        }
        assertEquals(method.toString() + " #" + i, isLeaking, map.get(method)[i]);
      }
    }
  }
  @Nullable
  public static SMAPAndMethodNode getMethodNode(
      byte[] classData, final String methodName, final String methodDescriptor, ClassId classId)
      throws ClassNotFoundException, IOException {
    ClassReader cr = new ClassReader(classData);
    final MethodNode[] node = new MethodNode[1];
    final String[] debugInfo = new String[2];
    final int[] lines = new int[2];
    lines[0] = Integer.MAX_VALUE;
    lines[1] = Integer.MIN_VALUE;
    cr.accept(
        new ClassVisitor(API) {

          @Override
          public void visitSource(String source, String debug) {
            super.visitSource(source, debug);
            debugInfo[0] = source;
            debugInfo[1] = debug;
          }

          @Override
          public MethodVisitor visitMethod(
              int access,
              @NotNull String name,
              @NotNull String desc,
              String signature,
              String[] exceptions) {
            if (methodName.equals(name) && methodDescriptor.equals(desc)) {
              node[0] =
                  new MethodNode(API, access, name, desc, signature, exceptions) {
                    @Override
                    public void visitLineNumber(int line, @NotNull Label start) {
                      super.visitLineNumber(line, start);
                      lines[0] = Math.min(lines[0], line);
                      lines[1] = Math.max(lines[1], line);
                    }
                  };
              return node[0];
            }
            return null;
          }
        },
        ClassReader.SKIP_FRAMES | (GENERATE_SMAP ? 0 : ClassReader.SKIP_DEBUG));

    SMAP smap =
        SMAPParser.parseOrCreateDefault(
            debugInfo[1], debugInfo[0], classId.toString(), lines[0], lines[1]);
    return new SMAPAndMethodNode(node[0], smap);
  }
 Module_attribute(ClassReader cr, int name_index, int length) throws IOException {
   super(name_index, length);
   requires_count = cr.readUnsignedShort();
   requires = new RequiresEntry[requires_count];
   for (int i = 0; i < requires_count; i++) requires[i] = new RequiresEntry(cr);
   exports_count = cr.readUnsignedShort();
   exports = new ExportsEntry[exports_count];
   for (int i = 0; i < exports_count; i++) exports[i] = new ExportsEntry(cr);
   uses_count = cr.readUnsignedShort();
   uses_index = new int[uses_count];
   for (int i = 0; i < uses_count; i++) uses_index[i] = cr.readUnsignedShort();
   provides_count = cr.readUnsignedShort();
   provides = new ProvidesEntry[provides_count];
   for (int i = 0; i < provides_count; i++) provides[i] = new ProvidesEntry(cr);
 }
  public Pair<ClassRepr, Set<UsageRepr.Usage>> analyze(final int fileName, final ClassReader cr) {
    final ClassCrawler visitor = new ClassCrawler(fileName);

    cr.accept(visitor, 0);

    return visitor.getResult();
  }
    protected Enter(Context context) {
		DEBUG.P(this,"Enter(1)");
		context.put(enterKey, this);

		log = Log.instance(context);
		reader = ClassReader.instance(context);
		make = TreeMaker.instance(context);
		syms = Symtab.instance(context);
		chk = Check.instance(context);
		memberEnter = MemberEnter.instance(context);
		annotate = Annotate.instance(context);
		lint = Lint.instance(context);

		predefClassDef = make.ClassDef(
			make.Modifiers(PUBLIC),
			syms.predefClass.name, null, null, null, null);
		//predefClass是一个ClassSymbol(PUBLIC|ACYCLIC, names.empty, rootPackage)
		//且它的Scope members_field已有成员(几个基本类型符号(symbols for basic types)及其他操作符)
		//请参考Systab类的predefClass字段说明
		predefClassDef.sym = syms.predefClass;

		todo = Todo.instance(context);
		fileManager = context.get(JavaFileManager.class);
		
		names = Name.Table.instance(context);    //我加上的
		DEBUG.P(0,this,"Enter(1)");
    }
 private List<Instruction> transformInvoke(InvokeInstruction insn) {
   if (insn.getType() != InvocationType.VIRTUAL) {
     return null;
   }
   MethodReference method = insn.getMethod();
   if (method.getClassName().equals(ResourceArray.class.getName())
       || method.getClassName().equals(ResourceMap.class.getName())) {
     if (method.getName().equals("keys")) {
       return transformKeys(insn);
     }
     InvokeInstruction accessInsn = new InvokeInstruction();
     accessInsn.setType(InvocationType.SPECIAL);
     ValueType[] types = new ValueType[method.getDescriptor().parameterCount() + 2];
     types[0] = ValueType.object("java.lang.Object");
     System.arraycopy(
         method.getDescriptor().getSignature(),
         0,
         types,
         1,
         method.getDescriptor().parameterCount() + 1);
     accessInsn.setMethod(
         new MethodReference(ResourceAccessor.class.getName(), method.getName(), types));
     accessInsn.getArguments().add(insn.getInstance());
     accessInsn.getArguments().addAll(insn.getArguments());
     accessInsn.setReceiver(insn.getReceiver());
     return Arrays.asList(accessInsn);
   }
   ClassReader iface = innerSource.get(method.getClassName());
   if (iface == null
       || !innerSource.isSuperType(Resource.class.getName(), iface.getName()).orElse(false)) {
     return null;
   }
   if (method.getName().startsWith("get")) {
     if (method.getName().length() > 3) {
       return transformGetterInvocation(insn, getPropertyName(method.getName().substring(3)));
     }
   } else if (method.getName().startsWith("is")) {
     if (method.getName().length() > 2) {
       return transformGetterInvocation(insn, getPropertyName(method.getName().substring(2)));
     }
   } else if (method.getName().startsWith("set")) {
     if (method.getName().length() > 3) {
       return transformSetterInvocation(insn, getPropertyName(method.getName().substring(3)));
     }
   }
   return null;
 }
  public String[] lookupParameterNames(
      AccessibleObject methodOrCtor, boolean throwExceptionIfMissing) {

    Class<?>[] types = null;
    Class<?> declaringClass = null;
    String name = null;
    if (methodOrCtor instanceof Method) {
      Method method = (Method) methodOrCtor;
      types = method.getParameterTypes();
      name = method.getName();
      declaringClass = method.getDeclaringClass();
    } else {
      Constructor<?> constructor = (Constructor<?>) methodOrCtor;
      types = constructor.getParameterTypes();
      declaringClass = constructor.getDeclaringClass();
      name = "<init>";
    }

    if (types.length == 0) {
      return EMPTY_NAMES;
    }
    InputStream byteCodeStream = getClassAsStream(declaringClass);
    if (byteCodeStream == null) {
      if (throwExceptionIfMissing) {
        throw new ParameterNamesNotFoundException("Unable to get class bytes");
      } else {
        return Paranamer.EMPTY_NAMES;
      }
    }
    try {
      ClassReader reader = new ClassReader(byteCodeStream);
      TypeCollector visitor = new TypeCollector(name, types, throwExceptionIfMissing);
      reader.accept(visitor);
      String[] parameterNamesForMethod = visitor.getParameterNamesForMethod();
      try {
        byteCodeStream.close();
      } catch (IOException e) {
      }
      return parameterNamesForMethod;
    } catch (IOException e) {
      if (throwExceptionIfMissing) {
        throw new ParameterNamesNotFoundException("IoException while reading class bytes", e);
      } else {
        return Paranamer.EMPTY_NAMES;
      }
    }
  }
Example #20
0
  public static void main(String[] args) {

    String fileName = null;
    ClassReader classReader = null;

    try {
      /* Filename should be the first command line argument */
      fileName = args[0];
    } catch (ArrayIndexOutOfBoundsException ex) {
      errorMessage("Usage: java Decompile <class file>");
    }
    try {
      try {
        /* Create ClassReader instance and fill it */
        classReader = new ClassReader(fileName);
        classReader.readAll();
      } catch (ClassFileMagicMismatch ex) {
        errorMessage("This does not appear to be a class file!");
      } catch (FileNotFoundException ex) {
        errorMessage("File not found!");
      } catch (EOFException ex) {
        errorMessage("Class file format seems to be invalid!");
      } catch (UnknownConstantPoolTag ex) {
        errorMessage("Class file format seems to be invalid" + " (unknown tag in constant pool)!");
      } catch (NullPointerException ex) {
        bug();
      } finally {
        /* we no longer need the file object in classReader */
        if (classReader != null) classReader.close();
      }
    } catch (IOException ex) {
      errorMessage("I/O error!");
    }
    /* Here goes the printing */
    System.out.format("\n/* File %s */%n", fileName);
    try {
      classReader.printNice();
    } catch (NullPointerException ex) {
      bug();
    }
  }
    /** Enter a set of generated class files. */
    private List<ClassSymbol> enterClassFiles(Map<String, JavaFileObject> classFiles) {
      ClassReader reader = ClassReader.instance(context);
      Names names = Names.instance(context);
      List<ClassSymbol> list = List.nil();

      for (Map.Entry<String, JavaFileObject> entry : classFiles.entrySet()) {
        Name name = names.fromString(entry.getKey());
        JavaFileObject file = entry.getValue();
        if (file.getKind() != JavaFileObject.Kind.CLASS) throw new AssertionError(file);
        ClassSymbol cs;
        if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) {
          Name packageName = Convert.packagePart(name);
          PackageSymbol p = reader.enterPackage(packageName);
          if (p.package_info == null)
            p.package_info = reader.enterClass(Convert.shortName(name), p);
          cs = p.package_info;
          if (cs.classfile == null) cs.classfile = file;
        } else cs = reader.enterClass(name, file);
        list = list.prepend(cs);
      }
      return list.reverse();
    }
 public byte[] process(byte[] input) {
   ClassWriter classWriter = new ClassWriter(false);
   ClassAdapter classAdapter =
       new ClassAdapter(classWriter) {
         @Override
         public MethodVisitor visitMethod(
             final int access,
             final String name,
             final String desc,
             final String signature,
             final String[] exceptions) {
           final MethodVisitor methodVisitor =
               super.visitMethod(access, name, desc, signature, exceptions);
           if ("<clinit>".equals(name)) {
             return new StaticInitRemovingAdapter(methodVisitor);
           } else {
             return methodVisitor;
           }
         }
       };
   ClassReader classReader = new ClassReader(input);
   classReader.accept(classAdapter, false);
   return classWriter.toByteArray();
 }
Example #23
0
  public void visitTopLevel(JCCompilationUnit tree) {
    JavaFileObject prev = log.useSource(tree.sourcefile);
    boolean addEnv = false;
    boolean isPkgInfo =
        tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE);
    if (tree.pid != null) {
      tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid));
      if (tree.packageAnnotations.nonEmpty()) {
        if (isPkgInfo) {
          addEnv = true;
        } else {
          log.error(tree.packageAnnotations.head.pos(), "pkg.annotations.sb.in.package-info.java");
        }
      }
    } else {
      tree.packge = syms.unnamedPackage;
    }
    tree.packge.complete(); // Find all classes in package.
    Env<AttrContext> env = topLevelEnv(tree);

    // Save environment of package-info.java file.
    if (isPkgInfo) {
      Env<AttrContext> env0 = typeEnvs.get(tree.packge);
      if (env0 == null) {
        typeEnvs.put(tree.packge, env);
      } else {
        JCCompilationUnit tree0 = env0.toplevel;
        if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
          log.warning(
              tree.pid != null ? tree.pid.pos() : null, "pkg-info.already.seen", tree.packge);
          if (addEnv
              || (tree0.packageAnnotations.isEmpty()
                  && tree.docComments != null
                  && tree.docComments.get(tree) != null)) {
            typeEnvs.put(tree.packge, env);
          }
        }
      }
    }
    classEnter(tree.defs, env);
    if (addEnv) {
      todo.append(env);
    }
    log.useSource(prev);
    result = null;
  }
Example #24
0
  protected Enter(Context context) {
    context.put(enterKey, this);

    log = Log.instance(context);
    reader = ClassReader.instance(context);
    make = TreeMaker.instance(context);
    syms = Symtab.instance(context);
    chk = Check.instance(context);
    memberEnter = MemberEnter.instance(context);
    types = Types.instance(context);
    annotate = Annotate.instance(context);
    lint = Lint.instance(context);

    predefClassDef =
        make.ClassDef(make.Modifiers(PUBLIC), syms.predefClass.name, null, null, null, null);
    predefClassDef.sym = syms.predefClass;
    todo = Todo.instance(context);
    fileManager = context.get(JavaFileManager.class);
  }
Example #25
0
 /**
  * Constructs a new {@link ClassWriter} object and enables optimizations for "mostly add" bytecode
  * transformations. These optimizations are the following:
  *
  * <ul>
  *   <li>The constant pool from the original class is copied as is in the new class, which saves
  *       time. New constant pool entries will be added at the end if necessary, but unused
  *       constant pool entries <i>won't be removed</i>.
  *   <li>Methods that are not transformed are copied as is in the new class, directly from the
  *       original class bytecode (i.e. without emitting visit events for all the method
  *       instructions), which saves a <i>lot</i> of time. Untransformed methods are detected by
  *       the fact that the {@link ClassReader} receives {@link MethodVisitor} objects that come
  *       from a {@link ClassWriter} (and not from a custom {@link ClassAdapter} or any other
  *       {@link ClassVisitor} instance).
  * </ul>
  *
  * @param classReader the {@link ClassReader} used to read the original class. It will be used to
  *     copy the entire constant pool from the original class and also to copy other fragments of
  *     original bytecode where applicable.
  * @param flags option flags that can be used to modify the default behavior of this class. See
  *     {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
  */
 public ClassWriter(final ClassReader classReader, final int flags) {
   this(flags);
   classReader.copyPool(this);
   this.cr = classReader;
 }
  /**
   * Construct a proxy generator. This generator is used when we need to create a proxy object for a
   * class or an interface given a map of closures.
   *
   * @param closureMap the delegates implementations
   * @param superClass corresponding to the superclass class visitor
   * @param interfaces extra interfaces the proxy should implement
   * @param proxyLoader the class loader which should be used to load the generated proxy
   * @param delegateClass if not null, generate a delegate field with the corresponding class
   * @param emptyBody if set to true, the unimplemented abstract methods will receive an empty body
   *     instead of throwing an {@link UnsupportedOperationException}.
   */
  public ProxyGeneratorAdapter(
      final Map<Object, Object> closureMap,
      final Class superClass,
      final Class[] interfaces,
      final ClassLoader proxyLoader,
      final boolean emptyBody,
      final Class delegateClass) {
    super(new ClassWriter(0));
    this.visitedMethods = new LinkedHashSet<Object>();
    this.delegatedClosures =
        closureMap.isEmpty() ? EMPTY_DELEGATECLOSURE_MAP : new HashMap<String, Boolean>();
    boolean wildcard = false;
    for (Map.Entry<Object, Object> entry : closureMap.entrySet()) {
      String name = entry.getKey().toString();
      if ("*".equals(name)) {
        wildcard = true;
      }
      this.delegatedClosures.put(name, Boolean.FALSE);
    }
    this.hasWildcard = wildcard;

    // if we have to delegate to another object, generate the appropriate delegate field
    // and collect the name of the methods for which delegation is active
    this.generateDelegateField = delegateClass != null;
    this.objectDelegateMethods =
        generateDelegateField
            ? createDelegateMethodList(delegateClass, interfaces)
            : EMPTY_STRING_SET;
    this.delegateClass = delegateClass;

    // a proxy is supposed to be a concrete class, so it cannot extend an interface.
    // If the provided superclass is an interface, then we replace the superclass with Object
    // and add this interface to the list of implemented interfaces
    boolean isSuperClassAnInterface = superClass.isInterface();
    this.superClass = isSuperClassAnInterface ? Object.class : superClass;

    // create the base list of classes which have possible methods to be overloaded
    this.classList = new LinkedList<Class>();
    this.classList.add(superClass);
    if (generateDelegateField) {
      classList.add(delegateClass);
    }
    if (interfaces != null) {
      Collections.addAll(this.classList, interfaces);
    }
    this.proxyName = proxyName();
    this.loader = proxyLoader != null ? new InnerLoader(proxyLoader) : findClassLoader(superClass);
    this.emptyBody = emptyBody;

    // generate bytecode
    ClassWriter writer = (ClassWriter) cv;
    ClassReader cr = createClassVisitor(Object.class);
    cr.accept(this, 0);
    byte[] b = writer.toByteArray();
    //        CheckClassAdapter.verify(new ClassReader(b), true, new PrintWriter(System.err));
    cachedClass = loader.defineClass(proxyName.replace('/', '.'), b);
    // cache no-arg constructor
    Class[] args =
        generateDelegateField ? new Class[] {Map.class, delegateClass} : new Class[] {Map.class};
    Constructor constructor;
    try {
      constructor = cachedClass.getConstructor(args);
    } catch (NoSuchMethodException e) {
      constructor = null;
    }
    cachedNoArgConstructor = constructor;
  }
Example #27
0
 SourceID_attribute(ClassReader cr, int name_index, int length) throws IOException {
   super(name_index, length);
   sourceID_index = cr.readUnsignedShort();
 }
Example #28
0
 /**
  * Constructs a new ClassWriter object and enables optimizations for "mostly add" bytecode
  * transformations. These optimizations are the following:
  *
  * <ul>
  *   <li>The constant pool from the original class is copied as is in the new class, which saves
  *       time. New constant pool entries will be added at the end if necessary, but unused
  *       constant pool entries <i>won't be removed</i>.
  *   <li>Methods that are not transformed are copied as is in the new class, directly from the
  *       original class bytecode (i.e. without emitting visit events for all the method
  *       instructions), which saves a <i>lot</i> of time. Untransformed methods are detected by
  *       the fact that the {@link ClassReader} receives {@link MethodVisitor} objects that come
  *       from a ClassWriter (and not from any other {@link ClassVisitor} instance).
  * </ul>
  *
  * @param classReader the {@link ClassReader} used to read the original class. It will be used to
  *     copy the entire constant pool from the original class and also to copy other fragments of
  *     original bytecode where applicable.
  * @param computeMaxs <tt>true</tt> if the maximum stack size and the maximum number of local
  *     variables must be automatically computed. If this flag is <tt>true</tt>, then the arguments
  *     of the {@link MethodVisitor#visitMaxs visitMaxs} method of the {@link MethodVisitor}
  *     returned by the {@link #visitMethod visitMethod} method will be ignored, and computed
  *     automatically from the signature and the bytecode of each method.
  */
 public ClassWriter(ClassReader classReader, boolean computeMaxs) {
   this(computeMaxs);
   classReader.copyPool(this);
   cr = classReader;
 }
Example #29
0
  public void visitClassDef(JCClassDecl tree) {
    Symbol owner = env.info.scope.owner;
    Scope enclScope = enterScope(env);
    ClassSymbol c;
    if (owner.kind == PCK) {
      // We are seeing a toplevel class.
      PackageSymbol packge = (PackageSymbol) owner;
      for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner) q.flags_field |= EXISTS;
      c = reader.enterClass(tree.name, packge);
      packge.members().enterIfAbsent(c);
      if ((tree.mods.flags & PUBLIC) != 0 && !classNameMatchesFileName(c, env)) {
        log.error(tree.pos(), "class.public.should.be.in.file", tree.name);
      }
    } else {
      if (!tree.name.isEmpty() && !chk.checkUniqueClassName(tree.pos(), tree.name, enclScope)) {
        result = null;
        return;
      }
      if (owner.kind == TYP) {
        // We are seeing a member class.
        c = reader.enterClass(tree.name, (TypeSymbol) owner);
        if ((owner.flags_field & INTERFACE) != 0) {
          tree.mods.flags |= PUBLIC | STATIC;
        }
      } else {
        // We are seeing a local class.
        c = reader.defineClass(tree.name, owner);
        c.flatname = chk.localClassName(c);
        if (!c.name.isEmpty()) chk.checkTransparentClass(tree.pos(), c, env.info.scope);
      }
    }
    tree.sym = c;

    // Enter class into `compiled' table and enclosing scope.
    if (chk.compiled.get(c.flatname) != null) {
      duplicateClass(tree.pos(), c);
      result = types.createErrorType(tree.name, (TypeSymbol) owner, Type.noType);
      tree.sym = (ClassSymbol) result.tsym;
      return;
    }
    chk.compiled.put(c.flatname, c);
    enclScope.enter(c);

    // Set up an environment for class block and store in `typeEnvs'
    // table, to be retrieved later in memberEnter and attribution.
    Env<AttrContext> localEnv = classEnv(tree, env);
    typeEnvs.put(c, localEnv);

    // Fill out class fields.
    c.completer = memberEnter;
    c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
    c.sourcefile = env.toplevel.sourcefile;
    c.members_field = new Scope(c);

    ClassType ct = (ClassType) c.type;
    if (owner.kind != PCK && (c.flags_field & STATIC) == 0) {
      // We are seeing a local or inner class.
      // Set outer_field of this class to closest enclosing class
      // which contains this class in a non-static context
      // (its "enclosing instance class"), provided such a class exists.
      Symbol owner1 = owner;
      while ((owner1.kind & (VAR | MTH)) != 0 && (owner1.flags_field & STATIC) == 0) {
        owner1 = owner1.owner;
      }
      if (owner1.kind == TYP) {
        ct.setEnclosingType(owner1.type);
      }
    }

    // Enter type parameters.
    ct.typarams_field = classEnter(tree.typarams, localEnv);

    // Add non-local class to uncompleted, to make sure it will be
    // completed later.
    if (!c.isLocal() && uncompleted != null) uncompleted.append(c);
    //      System.err.println("entering " + c.fullname + " in " + c.owner);//DEBUG

    // Recursively enter all member classes.
    classEnter(tree.defs, localEnv);

    result = c.type;
  }
  @NotNull
  public InlineResult doTransform(
      @NotNull AnonymousObjectGeneration anonymousObjectGen,
      @NotNull FieldRemapper parentRemapper) {
    final List<InnerClassNode> innerClassNodes = new ArrayList<InnerClassNode>();
    ClassBuilder classBuilder = createClassBuilder();
    final List<MethodNode> methodsToTransform = new ArrayList<MethodNode>();

    reader.accept(
        new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) {
          @Override
          public void visit(
              int version,
              int access,
              @NotNull String name,
              String signature,
              String superName,
              String[] interfaces) {
            InlineCodegenUtil.assertVersionNotGreaterThanJava6(version, name);
            super.visit(version, access, name, signature, superName, interfaces);
          }

          @Override
          public void visitInnerClass(
              @NotNull String name, String outerName, String innerName, int access) {
            innerClassNodes.add(new InnerClassNode(name, outerName, innerName, access));
          }

          @Override
          public MethodVisitor visitMethod(
              int access,
              @NotNull String name,
              @NotNull String desc,
              String signature,
              String[] exceptions) {
            MethodNode node = new MethodNode(access, name, desc, signature, exceptions);
            if (name.equals("<init>")) {
              if (constructor != null)
                throw new RuntimeException(
                    "Lambda, SAM or anonymous object should have only one constructor");

              constructor = node;
            } else {
              methodsToTransform.add(node);
            }
            return node;
          }

          @Override
          public FieldVisitor visitField(
              int access,
              @NotNull String name,
              @NotNull String desc,
              String signature,
              Object value) {
            addUniqueField(name);
            if (InlineCodegenUtil.isCapturedFieldName(name)) {
              return null;
            } else {
              return super.visitField(access, name, desc, signature, value);
            }
          }

          @Override
          public void visitSource(String source, String debug) {
            sourceInfo = source;
            debugInfo = debug;
          }

          @Override
          public void visitEnd() {}
        },
        ClassReader.SKIP_FRAMES);

    if (!inliningContext.isInliningLambda) {
      if (debugInfo != null && !debugInfo.isEmpty()) {
        sourceMapper = SourceMapper.Companion.createFromSmap(SMAPParser.parse(debugInfo));
      } else {
        // seems we can't do any clever mapping cause we don't know any about original class name
        sourceMapper = IdenticalSourceMapper.INSTANCE;
      }
      if (sourceInfo != null && !InlineCodegenUtil.GENERATE_SMAP) {
        classBuilder.visitSource(sourceInfo, debugInfo);
      }
    } else {
      if (sourceInfo != null) {
        classBuilder.visitSource(sourceInfo, debugInfo);
      }
      sourceMapper = IdenticalSourceMapper.INSTANCE;
    }

    ParametersBuilder allCapturedParamBuilder = ParametersBuilder.newBuilder();
    ParametersBuilder constructorParamBuilder = ParametersBuilder.newBuilder();
    List<CapturedParamInfo> additionalFakeParams =
        extractParametersMappingAndPatchConstructor(
            constructor,
            allCapturedParamBuilder,
            constructorParamBuilder,
            anonymousObjectGen,
            parentRemapper);
    List<MethodVisitor> deferringMethods = new ArrayList<MethodVisitor>();

    for (MethodNode next : methodsToTransform) {
      MethodVisitor deferringVisitor = newMethod(classBuilder, next);
      InlineResult funResult =
          inlineMethodAndUpdateGlobalResult(
              anonymousObjectGen,
              parentRemapper,
              deferringVisitor,
              next,
              allCapturedParamBuilder,
              false);

      Type returnType = Type.getReturnType(next.desc);
      if (!AsmUtil.isPrimitive(returnType)) {
        String oldFunReturnType = returnType.getInternalName();
        String newFunReturnType = funResult.getChangedTypes().get(oldFunReturnType);
        if (newFunReturnType != null) {
          inliningContext.typeRemapper.addAdditionalMappings(oldFunReturnType, newFunReturnType);
        }
      }
      deferringMethods.add(deferringVisitor);
    }

    for (MethodVisitor method : deferringMethods) {
      method.visitEnd();
    }

    generateConstructorAndFields(
        classBuilder,
        allCapturedParamBuilder,
        constructorParamBuilder,
        anonymousObjectGen,
        parentRemapper,
        additionalFakeParams);

    SourceMapper.Companion.flushToClassBuilder(sourceMapper, classBuilder);

    ClassVisitor visitor = classBuilder.getVisitor();
    for (InnerClassNode node : innerClassNodes) {
      visitor.visitInnerClass(node.name, node.outerName, node.innerName, node.access);
    }

    writeOuterInfo(visitor);

    classBuilder.done();

    anonymousObjectGen.setNewLambdaType(newLambdaType);
    return transformationResult;
  }