private static void dodgeExtendedStringLiterals(EcjTreePrinter printer) {
   printer.skipProperty(StringLiteral.class, "lineNumber");
   printer.skipPropertyIfHasValue(ExtendedStringLiteral.class, "lineNumber", -1);
   printer.skipPropertyIfHasValue(ExtendedStringLiteral.class, "lineNumber", -2);
   printer.skipPropertyIfHasValue(StringLiteral.class, "lineNumber", -1);
   printer.skipPropertyIfHasValue(StringLiteral.class, "lineNumber", -2);
   printer.stringReplace("ExtendedStringLiteral", "StringLiteral");
 }
 private static String convertToString0(ASTNode tree, EcjTreePrinter printer) {
   dodgePostFixArraysInVarDeclarations(printer);
   dodgeCombinedBinaryExpressions(printer);
   dodgeExtendedStringLiterals(printer);
   printer.visit(tree);
   String string = printer.getContent();
   return string;
 }
 private static void dodgeCombinedBinaryExpressions(EcjTreePrinter printer) {
   printer.skipProperty(CombinedBinaryExpression.class, "arity");
   printer.skipProperty(CombinedBinaryExpression.class, "arityMax");
   printer.skipProperty(CombinedBinaryExpression.class, "referencesTable");
   printer.stringReplace("CombinedBinaryExpression", "BinaryExpression");
 }
 /*
  * boolean[] s, t; results in 1 TypeReference, pointed at by both LocalDeclarations.
  * boolean s[], t[]; results in 2 identical TypeReference instances, but we can't figure that out and get it wrong.
  * It doesn't actually matter though, and it's virtually impossible to get right (would involve having to reparse source).
  */
 private static void dodgePostFixArraysInVarDeclarations(EcjTreePrinter printer) {
   printer.skipReferenceTracking(LocalDeclaration.class, TypeReference.class);
   printer.skipReferenceTracking(FieldDeclaration.class, TypeReference.class);
 }
 public static String convertToStringNoPositions(ASTNode tree) {
   return convertToString0(tree, EcjTreePrinter.printerWithoutPositions());
 }