protected ClassVisitor createClassVisitor() {
    CompilerConfiguration config = getConfiguration();
    int computeMaxStackAndFrames = ClassWriter.COMPUTE_MAXS;
    if (CompilerConfiguration.isPostJDK7(config.getTargetBytecode())
        || Boolean.TRUE.equals(config.getOptimizationOptions().get("indy"))) {
      computeMaxStackAndFrames += ClassWriter.COMPUTE_FRAMES;
    }
    return new ClassWriter(computeMaxStackAndFrames) {
      private ClassNode getClassNode(String name) {
        // try classes under compilation
        CompileUnit cu = getAST();
        ClassNode cn = cu.getClass(name);
        if (cn != null) return cn;
        // try inner classes
        cn = cu.getGeneratedInnerClass(name);
        if (cn != null) return cn;
        // try class loader classes
        try {
          cn = ClassHelper.make(cu.getClassLoader().loadClass(name, false, true), false);
        } catch (Exception e) {
          throw new GroovyBugError(e);
        }
        return cn;
      }

      private ClassNode getCommonSuperClassNode(ClassNode c, ClassNode d) {
        // adapted from ClassWriter code
        if (c.isDerivedFrom(d)) return d;
        if (d.isDerivedFrom(c)) return c;
        if (c.isInterface() || d.isInterface()) return ClassHelper.OBJECT_TYPE;
        do {
          c = c.getSuperClass();
        } while (c != null && !d.isDerivedFrom(c));
        if (c == null) return ClassHelper.OBJECT_TYPE;
        return c;
      }

      @Override
      protected String getCommonSuperClass(String arg1, String arg2) {
        ClassNode a = getClassNode(arg1.replace('/', '.'));
        ClassNode b = getClassNode(arg2.replace('/', '.'));
        return getCommonSuperClassNode(a, b).getName().replace('.', '/');
      }
    };
  }
 /**
  * Copy constructor. Use this if you have a mostly correct configuration for your compilation but
  * you want to make a some changes programmatically. An important reason to prefer this approach
  * is that your code will most likely be forward compatible with future changes to this
  * configuration API.<br>
  * An example of this copy constructor at work:<br>
  *
  * <pre>
  *    // In all likelihood there is already a configuration in your code's context
  *    // for you to copy, but for the sake of this example we'll use the global default.
  *    CompilerConfiguration myConfiguration = new CompilerConfiguration(CompilerConfiguration.DEFAULT);
  *    myConfiguration.setDebug(true);
  * </pre>
  *
  * @param configuration The configuration to copy.
  */
 public CompilerConfiguration(CompilerConfiguration configuration) {
   setWarningLevel(configuration.getWarningLevel());
   setOutput(configuration.getOutput());
   setTargetDirectory(configuration.getTargetDirectory());
   setClasspathList(new LinkedList(configuration.getClasspath()));
   setVerbose(configuration.getVerbose());
   setDebug(configuration.getDebug());
   setTolerance(configuration.getTolerance());
   setScriptBaseClass(configuration.getScriptBaseClass());
   setRecompileGroovySource(configuration.getRecompileGroovySource());
   setMinimumRecompilationInterval(configuration.getMinimumRecompilationInterval());
   setTargetBytecode(configuration.getTargetBytecode());
   setDefaultScriptExtension(configuration.getDefaultScriptExtension());
   setSourceEncoding(configuration.getSourceEncoding());
   setOutput(configuration.getOutput());
   setTargetDirectory(configuration.getTargetDirectory());
   Map jointCompilationOptions = configuration.getJointCompilationOptions();
   if (jointCompilationOptions != null) {
     jointCompilationOptions = new HashMap(jointCompilationOptions);
   }
   setJointCompilationOptions(jointCompilationOptions);
   setPluginFactory(configuration.getPluginFactory());
 }