private TypeDeclarationError reportDeclarationDiff(
     ClassFieldInspector cfi, AbstractClassTypeDeclarationDescr typeDescr) {
   List<String> existing = new ArrayList<String>();
   for (String existingFieldName : cfi.getFieldTypesField().keySet()) {
     if (!cfi.isNonGetter(existingFieldName)
         && !"class".equals(existingFieldName)
         && cfi.getSetterMethods().containsKey(existingFieldName)) {
       existing.add(existingFieldName);
     }
   }
   Collections.sort(existing);
   List<String> declared = new ArrayList<String>(typeDescr.getFields().keySet());
   Collections.sort(declared);
   List<String> deltas = new ArrayList<String>();
   for (String s : existing) {
     if (!declared.contains(s)) {
       deltas.add("--" + s);
     }
   }
   for (String s : declared) {
     if (!existing.contains(s)) {
       deltas.add("++" + s);
     }
   }
   return new TypeDeclarationError(
       typeDescr,
       "New declaration of "
           + typeDescr.getType().getFullName()
           + " can't declare a different set of fields \n"
           + "existing : "
           + existing
           + "\n"
           + "declared : "
           + declared
           + "\n"
           + "diff : "
           + deltas);
 }
  protected void checkRedeclaration(
      AbstractClassTypeDeclarationDescr typeDescr,
      TypeDeclaration type,
      PackageRegistry pkgRegistry) {
    TypeDeclaration previousTypeDeclaration =
        kbuilder
            .getPackageRegistry(typeDescr.getNamespace())
            .getPackage()
            .getTypeDeclaration(typeDescr.getTypeName());

    try {
      // if there is no previous declaration, then the original declaration was a POJO
      // to the behavior previous these changes
      if (previousTypeDeclaration == null) {
        // new declarations of a POJO can't declare new fields,
        // except if the POJO was previously generated/compiled and saved into the kjar
        Class<?> existingDeclarationClass =
            TypeDeclarationUtils.getExistingDeclarationClass(typeDescr, pkgRegistry);
        if (!kbuilder.getBuilderConfiguration().isPreCompiled()
            && !GeneratedFact.class.isAssignableFrom(existingDeclarationClass)
            && !type.getTypeClassDef().getFields().isEmpty()) {
          try {
            Class existingClass =
                pkgRegistry
                    .getPackage()
                    .getTypeResolver()
                    .resolveType(typeDescr.getType().getFullName());
            ClassFieldInspector cfi = new ClassFieldInspector(existingClass);

            int fieldCount = 0;
            for (String existingFieldName : cfi.getFieldTypesField().keySet()) {
              if (!cfi.isNonGetter(existingFieldName)
                  && !"class".equals(existingFieldName)
                  && cfi.getSetterMethods().containsKey(existingFieldName)
                  && cfi.getGetterMethods().containsKey(existingFieldName)) {
                if (!typeDescr.getFields().containsKey(existingFieldName)) {
                  type.setValid(false);
                  kbuilder.addBuilderResult(
                      new TypeDeclarationError(
                          typeDescr,
                          "New declaration of "
                              + typeDescr.getType().getFullName()
                              + " does not include field "
                              + existingFieldName));
                } else {
                  String fldType = cfi.getFieldTypes().get(existingFieldName).getName();
                  fldType =
                      TypeDeclarationUtils.toBuildableType(fldType, kbuilder.getRootClassLoader());
                  TypeFieldDescr declaredField = typeDescr.getFields().get(existingFieldName);
                  if (!fldType.equals(
                      type.getTypeClassDef().getField(existingFieldName).getTypeName())) {
                    type.setValid(false);
                    kbuilder.addBuilderResult(
                        new TypeDeclarationError(
                            typeDescr,
                            "New declaration of "
                                + typeDescr.getType().getFullName()
                                + " redeclared field "
                                + existingFieldName
                                + " : \n"
                                + "existing : "
                                + fldType
                                + " vs declared : "
                                + declaredField.getPattern().getObjectType()));
                  } else {
                    fieldCount++;
                  }
                }
              }
            }

            if (fieldCount != typeDescr.getFields().size()) {
              kbuilder.addBuilderResult(reportDeclarationDiff(cfi, typeDescr));
            }
          } catch (IOException e) {
            e.printStackTrace();
            type.setValid(false);
            kbuilder.addBuilderResult(
                new TypeDeclarationError(
                    typeDescr,
                    "Unable to redeclare "
                        + typeDescr.getType().getFullName()
                        + " : "
                        + e.getMessage()));
          } catch (ClassNotFoundException e) {
            type.setValid(false);
            kbuilder.addBuilderResult(
                new TypeDeclarationError(
                    typeDescr,
                    "Unable to redeclare "
                        + typeDescr.getType().getFullName()
                        + " : "
                        + e.getMessage()));
          }
        }
      } else {

        int typeComparisonResult = this.compareTypeDeclarations(previousTypeDeclaration, type);

        if (typeComparisonResult < 0) {
          // oldDeclaration is "less" than newDeclaration -> error
          kbuilder.addBuilderResult(
              new TypeDeclarationError(
                  typeDescr,
                  typeDescr.getType().getFullName()
                      + " declares more fields than the already existing version"));
          type.setValid(false);
        } else if (typeComparisonResult > 0 && !type.getTypeClassDef().getFields().isEmpty()) {
          // oldDeclaration is "grater" than newDeclaration -> error
          kbuilder.addBuilderResult(
              new TypeDeclarationError(
                  typeDescr,
                  typeDescr.getType().getFullName()
                      + " declares less fields than the already existing version"));
          type.setValid(false);
        }

        // if they are "equal" -> no problem

        // in the case of a declaration, we need to copy all the
        // fields present in the previous declaration
        if (type.getNature() == TypeDeclaration.Nature.DECLARATION) {
          mergeTypeDeclarations(previousTypeDeclaration, type);
        }
      }

    } catch (IncompatibleClassChangeError error) {
      // if the types are incompatible -> error
      kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, error.getMessage()));
    }
  }