void () { String s1 = """ try { em.persist(p); } catch (PersistenceException e) { // good }"""; String s2 = "try { '_TryStatement; } catch('_ExceptionType '_ExceptionDcl) { /* '_CommentContent */ }"; String replacement = "try { $TryStatement$; } catch($ExceptionType$ $ExceptionDcl$) { _logger.warning(\"$CommentContent$\", $ExceptionDcl$); }"; String expected = "try { em.persist(p); } catch(PersistenceException e) { _logger.warning(\" good\", e); }"; assertEquals(expected, replace(s1, s2, replacement)); final String in1 = """ try { System.out.println(1); } catch (RuntimeException e) { System.out.println(2); } finally { System.out.println(3); } """; final String what1 = """ try { '_Statement1; } finally { '_Statement2; }"""; final String by1 = """ try { // comment1 $Statement1$; } finally { // comment2 $Statement2$; }"""; final String expected1 = """ try { // comment1 System.out.println(1); } catch (RuntimeException e) { System.out.println(2); } finally { // comment2 System.out.println(3); } """; assertEquals("Replacing try/finally should leave unmatched catch sections alone", expected1, replace(in1, what1, by1)); final String in2 = """ try (AutoCloseable a = null) { System.out.println(1); } catch (Exception e) { System.out.println(2); } finally { System.out.println(3); }"""; final String what2 = """ try { '_Statement*; }"""; final String by2 = """ try { /* comment */ $Statement$; }"""; final String expected2 = """ try (AutoCloseable a = null) { /* comment */ System.out.println(1); } catch (Exception e) { System.out.println(2); } finally { System.out.println(3); }"""; assertEquals("Replacing try/finally should also keep unmatched resource lists and finally blocks", expected2, replace(in2, what2, by2)); final String in3 = """ class Foo { { try { } catch (NullPointerException e) { } catch (IllegalArgumentException e) { } catch (Exception ignored) { } } }"""; final String what3 = """ try { } catch(Exception ignored) { }"""; final String by3 = """ try { // 1 } catch(Exception ignored) { //2 }"""; assertEquals("don't break the order of catch blocks", """ class Foo { { try { // 1 } catch (NullPointerException e) { } catch (IllegalArgumentException e) { } catch(Exception ignored) { //2 } } }""", replace(in3, what3, by3)); }