void () { String source = """ public interface IntFunction<R> { R apply(int value); } public interface Function<T, R> { R apply(T t); } class A { void m() { Runnable q = () -> { /*comment*/ }; Runnable r = () -> { System.out.println(); }; IntFunction<String> f = a -> "hello"; Function<String, String> g = a -> "world"; } }"""; String pattern1 = "() -> '_body"; assertEquals("should find lambdas", 4, findMatchesCount(source, pattern1)); String pattern2 = "(int '_a) -> '_body"; assertEquals("should find lambdas with specific parameter type", 1, findMatchesCount(source, pattern2)); String pattern3 = "('_a{0,0})->'_body"; assertEquals("should find lambdas without any parameters", 2, findMatchesCount(source, pattern3)); String pattern4 = "()->System.out.println()"; assertEquals("should find lambdas with matching body", 1, findMatchesCount(source, pattern4)); String pattern5 = "()->{/*comment*/}"; assertEquals("should find lambdas with comment body", 1, findMatchesCount(source, pattern5)); String pattern6 = "('_Parameter+) -> System.out.println()"; assertEquals("should find lambdas with at least one parameter and matching body", 0, findMatchesCount(source, pattern6)); String typePattern = "'_X:[exprtype( Runnable )]"; assertEquals("should find Runnable lambda's", 2, findMatchesCount(source, typePattern)); String source2 = """ import java.util.function.Function; public class Test { public static void main(String[] args) { System.out.println(Function.<String>identity().andThen((a) -> { String prefix = a; return new Function<String, String>() { @Override public String apply(String b) { return prefix + b; } }; }).apply("a").apply("b")); } }"""; String pattern7 = """ (a) -> { '_Statement; return new Function<String, String>() { public String apply(String b) { '_Statement2; } }; }"""; assertEquals("match statement body correctly", 1, findMatchesCount(source2, pattern7)); String source3 = """ class LambdaParameter { void x() { Runnable r = (var a) -> a = ""; } }"""; String pattern8 = "String '_x;"; assertEquals("avoid IncorrectOperationException", 0, findMatchesCount(source3, pattern8)); String source4 = """ class Main2 { public static void main(String[] args) { //need to match this JSTestUtils.testES6("myProject", () -> { doTest1(); doTest2(); }); } private static void doTest1() { } private static void doTest2() { } static class JSTestUtils { private JSTestUtils() { } static void testES6(Object project, Runnable runnable) { runnable.run(); } } }"""; String pattern9 = """ JSTestUtils.testES6('_expression, () -> { '_statements*; })"""; assertEquals("match lambda body correctly", 1, findMatchesCount(source4, pattern9)); String source5 = """ class X { void x() { Runnable r = () -> {}; } }"""; String pattern10 = "() -> '_B"; assertEquals("match empty lambda expression body", 1, findMatchesCount(source5, pattern10)); final String pattern11 = "() -> { '_body*; }"; assertEquals("match empty lambda expression body 2", 1, findMatchesCount(source5, pattern11)); String source6 = """ class X { void x() { Runnable r = () -> { // comment System.out.println(); System.out.println(); }; } }"""; assertEquals("match lambda code block body", 1, findMatchesCount(source6, pattern10)); assertEquals("match lambda body starting with comment", 1, findMatchesCount(source6, pattern11)); }