Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8308637

AssertionError when using Trees.getScope in plug-in

XMLWordPrintable

    • generic
    • generic

      A DESCRIPTION OF THE PROBLEM :
      I have a javac plug-in (see its source code below), that passes through an AST and tries to call Trees.getScope for an IdentifierTree in NewClassTree. The plug-in is run on the next code:

      ==========
      class A {}
      class B {
          public class I {
          }
          void m() {
              this.new I() {
              };
          }
      }
      ==========

      When Trees.getScope is invoked for a TreePath of an IdentifierNode in `this.new I() { };`, AssertionError is thrown.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Compile the plug-in:
          $ javac src/main/java/example/TestPlugin.java -d out/
          $ cp -r src/main/resources/* out/
          $ cd out
          $ jar cvf test-plugin.jar *
      2. Run plug-in on the given example:
          $ javac Bad.java -Xplugin:TestPlugin -cp out/test-plugin.jar

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Plug-in should print:

      ==========
      Resolving scope of anonymous class ident...
      Success: ...
      ==========
      ACTUAL -
      com.sun.tools.javac.util.ClientCodeException: java.lang.AssertionError
      at jdk.compiler/com.sun.tools.javac.api.ClientCodeWrapper$WrappedTaskListener.finished(ClientCodeWrapper.java:858)
      at jdk.compiler/com.sun.tools.javac.api.MultiTaskListener.finished(MultiTaskListener.java:132)
      at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1394)
      at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1351)
      at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:946)
      at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:317)
      at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:176)
      at jdk.compiler/com.sun.tools.javac.Main.compile(Main.java:64)
      at jdk.compiler/com.sun.tools.javac.Main.main(Main.java:50)
      Caused by: java.lang.AssertionError
      at jdk.compiler/com.sun.tools.javac.util.Assert.error(Assert.java:155)
      at jdk.compiler/com.sun.tools.javac.util.Assert.check(Assert.java:46)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribClassBody(Attr.java:5390)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribClass(Attr.java:5353)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribClass(Attr.java:5184)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.visitClassDef(Attr.java:980)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:819)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:677)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribStat(Attr.java:751)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.visitAnonymousClassDefinition(Attr.java:2960)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.visitNewClass(Attr.java:2851)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCNewClass.accept(JCTree.java:1852)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:677)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribExpr(Attr.java:730)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.visitExec(Attr.java:2276)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCExpressionStatement.accept(JCTree.java:1584)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:677)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribStat(Attr.java:751)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribStats(Attr.java:770)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.visitBlock(Attr.java:1448)
      at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1091)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:677)
      at jdk.compiler/com.sun.tools.javac.comp.DeferredAttr.attribSpeculative(DeferredAttr.java:500)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribToTree(Attr.java:429)
      at jdk.compiler/com.sun.tools.javac.comp.Attr.attribStatToTree(Attr.java:422)
      at jdk.compiler/com.sun.tools.javac.api.JavacTrees.attribStatToTree(JavacTrees.java:943)
      at jdk.compiler/com.sun.tools.javac.api.JavacTrees.getAttrContext(JavacTrees.java:918)
      at jdk.compiler/com.sun.tools.javac.api.JavacTrees.getScope(JavacTrees.java:798)
      at jdk.compiler/com.sun.tools.javac.api.JavacTrees.getScope(JavacTrees.java:166)
      at example.TestPlugin$Visitor.visitIdentifier(TestPlugin.java:79)
              ...

      ---------- BEGIN SOURCE ----------
      Plugin source code (src/main/java/example/TestPlugin.java):
      ==========
      package example;

      import com.sun.source.tree.*;
      import com.sun.source.util.*;

      public class TestPlugin implements Plugin {
          @Override
          public String getName() {
              return "TestPlugin";
          }

          @Override
          public void init(JavacTask javacTask, String... strings) {
              Trees trees = Trees.instance(javacTask);
              Visitor visitor = new Visitor(trees);

              javacTask.addTaskListener(new TaskListener() {
                  @Override
                  public void finished(TaskEvent e) {
                      if (e.getKind() != TaskEvent.Kind.ANALYZE) return;
                      e.getCompilationUnit().accept(visitor, null);
                  }
              });
          }

          private static class Visitor extends SimpleTreeVisitor<Void, Void> {
              private final Trees trees;
              private CompilationUnitTree compilationUnit;

              private Visitor(Trees trees) {
                  this.trees = trees;
              }

              @Override
              public Void visitCompilationUnit(CompilationUnitTree node, Void unused) {
                  this.compilationUnit = node;
                  for (Tree decl : node.getTypeDecls()) {
                      decl.accept(this, unused);
                  }
                  return unused;
              }

              @Override
              public Void visitClass(ClassTree node, Void unused) {
                  for (Tree member : node.getMembers()) {
                      member.accept(this, unused);
                  }
                  return unused;
              }

              @Override
              public Void visitMethod(MethodTree node, Void unused) {
                  for (StatementTree statement : node.getBody().getStatements()) {
                      statement.accept(this, unused);
                  }
                  return unused;
              }

              @Override
              public Void visitExpressionStatement(ExpressionStatementTree node, Void unused) {
                  node.getExpression().accept(this, unused);
                  return unused;
              }

              @Override
              public Void visitNewClass(NewClassTree node, Void unused) {
                  node.getIdentifier().accept(this, unused);
                  return unused;
              }

              @Override
              public Void visitIdentifier(IdentifierTree node, Void unused) {
                  if (compilationUnit == null) return unused;

                  TreePath treePath = TreePath.getPath(compilationUnit, node);
                  if (treePath == null) return unused;

                  System.out.println("Resolving scope of anonymous class ident...");
                  Scope scope = trees.getScope(treePath);
                  System.out.println("Success: " + scope);

                  return unused;
              }
          }
      }
      ==========

      src/main/resources/META-INF/services/com.sun.source.util.Plugin:
      ==========
      example.TestPlugin
      ==========

      Code that causes the crash (Bad.java):
      ==========
      class A {}
      class B {
          public class I {
          }
          void m() {
              this.new I() {
              };
          }
      }
      ==========
      ---------- END SOURCE ----------

      FREQUENCY : always


            jlahoda Jan Lahoda
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: