@Test
  public void testStatements() {
    String expected1 =
        literal(
            "[B ClassDeclaration X (20-80)]",
            "    [I Modifiers (20-20)]",
            "    typeName: [I Identifier X (20-20)]",
            "        PROPERTY: name = X",
            "    [B NormalTypeBody (20-80)]",
            "            [B InstanceInitializer (20-80)]",
            "                [B Block (20-80)]",
            "                        [B Synchronized (60-80)]",
            "                            lock: [I This (60-80)]",
            "                            [B Block (60-80)]");

    ClassDeclaration classDecl = (ClassDeclaration) Template.parseMember("class X {{foo:;}}");
    {
      Template<ClassDeclaration> template = Template.of(classDecl);
      Statement x = new Synchronized().astBody(new Block()).astLock(new This());
      Ast.setAllPositions(x, new Position(60, 80));
      template.setStartPosition(20);
      template.replaceStatement("foo", x);
      ClassDeclaration finish = template.finish();
      StructureFormatter sf = StructureFormatter.formatterWithPositions();
      finish.accept(new SourcePrinter(sf));
      assertEquals(expected1, sf.finish());
    }

    {
      Template<ClassDeclaration> template = Template.of(classDecl);
      Statement x = new Synchronized().astBody(new Block()).astLock(new This());
      template.setStartPosition(20);
      template.replaceStatement("foo", x, new Position(60, 80));
      ClassDeclaration finish = template.finish();
      StructureFormatter sf = StructureFormatter.formatterWithPositions();
      finish.accept(new SourcePrinter(sf));
      assertEquals(expected1, sf.finish());
    }

    String expected2 =
        literal(
            "[B ClassDeclaration X (20-200)]",
            "    [I Modifiers (20-20)]",
            "    typeName: [I Identifier X (20-20)]",
            "        PROPERTY: name = X",
            "    [B NormalTypeBody (20-200)]",
            "            [B InstanceInitializer (20-200)]",
            "                [B Block (20-200)]",
            "                        [B Synchronized (40-50)]",
            "                            lock: [I This (40-50)]",
            "                            [B Block (40-50)]",
            "                        [B While (100-200)]",
            "                            condition: [I BooleanLiteral (100-200)]",
            "                                PROPERTY: value = true",
            "                            [B EmptyStatement (100-200)]");

    {
      Template<ClassDeclaration> template = Template.of(classDecl);
      Statement x = new Synchronized().astBody(new Block()).astLock(new This());
      Statement y =
          new While()
              .astCondition(new BooleanLiteral().astValue(true))
              .astStatement(new EmptyStatement());
      Ast.setAllPositions(x, new Position(40, 50));
      Ast.setAllPositions(y, new Position(100, 200));
      template.setStartPosition(20);
      template.replaceStatement("foo", Arrays.asList(x, y));
      ClassDeclaration finish = template.finish();
      StructureFormatter sf = StructureFormatter.formatterWithPositions();
      finish.accept(new SourcePrinter(sf));
      assertEquals(expected2, sf.finish());
    }
  }