private void changeBaseScriptType(
      final AnnotatedNode parent, final ClassNode cNode, final ClassNode baseScriptType) {
    if (!cNode.isScriptBody()) {
      addError("Annotation " + MY_TYPE_NAME + " can only be used within a Script.", parent);
      return;
    }

    if (!baseScriptType.isScript()) {
      addError(
          "Declared type " + baseScriptType + " does not extend groovy.lang.Script class!", parent);
      return;
    }

    cNode.setSuperClass(baseScriptType);

    // Method in base script that will contain the script body code.
    MethodNode runScriptMethod = ClassHelper.findSAM(baseScriptType);

    // If they want to use a name other than than "run", then make the change.
    if (isCustomScriptBodyMethod(runScriptMethod)) {
      MethodNode defaultMethod = cNode.getDeclaredMethod("run", Parameter.EMPTY_ARRAY);
      // GROOVY-6706: Sometimes an NPE is thrown here.
      // The reason is that our transform is getting called more than once sometimes.
      if (defaultMethod != null) {
        cNode.removeMethod(defaultMethod);
        MethodNode methodNode =
            new MethodNode(
                runScriptMethod.getName(),
                runScriptMethod.getModifiers() & ~ACC_ABSTRACT,
                runScriptMethod.getReturnType(),
                runScriptMethod.getParameters(),
                runScriptMethod.getExceptions(),
                defaultMethod.getCode());
        // The AST node metadata has the flag that indicates that this method is a script body.
        // It may also be carrying data for other AST transforms.
        methodNode.copyNodeMetaData(defaultMethod);
        cNode.addMethod(methodNode);
      }
    }

    // If the new script base class does not have a contextual constructor (g.l.Binding), then we
    // won't either.
    // We have to do things this way (and rely on just default constructors) because the logic that
    // generates
    // the constructors for our script class have already run.
    if (cNode.getSuperClass().getDeclaredConstructor(CONTEXT_CTOR_PARAMETERS) == null) {
      ConstructorNode orphanedConstructor = cNode.getDeclaredConstructor(CONTEXT_CTOR_PARAMETERS);
      cNode.removeConstructor(orphanedConstructor);
    }
  }
  private Variable findClassMember(ClassNode cn, String name) {
    if (cn == null) return null;
    if (cn.isScript()) {
      return new DynamicVariable(name, false);
    }

    for (FieldNode fn : cn.getFields()) {
      if (fn.getName().equals(name)) return fn;
    }

    for (MethodNode mn : cn.getMethods()) {
      String pName = getPropertyName(mn);
      // GRECLIPSE: start
      // must set the declaringClass
      /*old{
      if (pName != null && pName.equals(name))
          return new PropertyNode(pName, mn.getModifiers(), getPropertyType(mn), cn, null, null, null);
          */
      // newcode
      if (pName != null && pName.equals(name)) {
        PropertyNode property =
            new PropertyNode(pName, mn.getModifiers(), getPropertyType(mn), cn, null, null, null);
        property.setDeclaringClass(cn);
        property.getField().setDeclaringClass(cn);
        return property;
      }
      // GRECLIPSE: end
    }

    for (PropertyNode pn : cn.getProperties()) {
      if (pn.getName().equals(name)) return pn;
    }

    Variable ret = findClassMember(cn.getSuperClass(), name);
    if (ret != null) return ret;
    return findClassMember(cn.getOuterClass(), name);
  }