20
20
import java .util .List ;
21
21
import java .util .Map ;
22
22
import java .util .Objects ;
23
+ import java .util .Optional ;
23
24
import org .eclipse .jdt .core .JavaCore ;
24
25
import org .eclipse .jdt .core .dom .AST ;
25
26
import org .eclipse .jdt .core .dom .ASTParser ;
@@ -779,6 +780,7 @@ default void forEach(java.util.function.Consumer<? super T> action) {
779
780
assertThat (superKeyword .symbolType ().fullyQualifiedName ()).isEqualTo ("java.lang.Iterable" );
780
781
}
781
782
783
+ /** Check that the owner of a lambda parameter is the field to which it is assigned. */
782
784
@ Test
783
785
void expression_lambda () {
784
786
String source = """
@@ -793,15 +795,47 @@ class A {
793
795
LambdaExpressionTreeImpl lambda = (LambdaExpressionTreeImpl ) f .initializer ();
794
796
VariableTreeImpl p = (VariableTreeImpl ) lambda .parameters ().get (0 );
795
797
796
- // owner of lambda parameter is the method which defines the functional interface
797
798
Symbol newSymbol = cu .sema .variableSymbol (p .variableBinding );
798
799
assertThat (newSymbol .declaration ().firstToken ().range ().start ().line ()).isEqualTo (3 );
799
800
Symbol newOwner = newSymbol .owner ();
800
801
assertThat (newOwner ).isNotNull ();
801
- assertThat (newOwner .isMethodSymbol ()).isTrue ();
802
+ assertThat (newOwner .isVariableSymbol ()).isTrue ();
803
+ assertThat (newOwner .isTypeSymbol ()).isFalse ();
804
+ assertThat (newOwner .name ()).isEqualTo ("f" );
805
+ assertThat (newOwner .owner ().type ().fullyQualifiedName ()).isEqualTo ("org.foo.A" );
806
+ }
807
+
808
+ /** Check that the owner of lambda parameter is the method inside which the lambda is declared. */
809
+ @ Test
810
+ void expression_lambda_variable_owner () {
811
+ String source = """
812
+ package org.foo;
813
+ class A {
814
+ void foo() {
815
+ java.util.function.Consumer<String> v = p -> { };
816
+ }
817
+ }
818
+ """ ;
819
+ JavaTree .CompilationUnitTreeImpl cu = test (source );
820
+ ClassTreeImpl c = (ClassTreeImpl ) cu .types ().get (0 );
821
+ MethodTreeImpl foo = (MethodTreeImpl ) c .members ().get (0 );
822
+ Optional <BlockTreeImpl > firstBlock = foo .getChildren ().stream ()
823
+ .filter (BlockTreeImpl .class ::isInstance )
824
+ .map (BlockTreeImpl .class ::cast )
825
+ .findFirst ();
826
+ VariableTree v = (VariableTree ) firstBlock .get ().body ().get (0 );
827
+ LambdaExpressionTreeImpl lambda = (LambdaExpressionTreeImpl ) v .initializer ();
828
+ VariableTreeImpl p = (VariableTreeImpl ) lambda .parameters ().get (0 );
829
+
830
+ // owner of lambda parameter is the field or variable to which it is assigned
831
+ Symbol newSymbol = cu .sema .variableSymbol (p .variableBinding );
832
+ Symbol newOwner = newSymbol .owner ();
833
+ assertThat (newOwner ).isNotNull ();
834
+ assertThat (newOwner .isVariableSymbol ()).isFalse ();
802
835
assertThat (newOwner .isTypeSymbol ()).isFalse ();
803
- assertThat (newOwner .name ()).isEqualTo ("accept" );
804
- assertThat (newOwner .owner ().type ().fullyQualifiedName ()).isEqualTo ("java.util.function.Consumer" );
836
+ assertThat (newOwner .isMethodSymbol ()).isTrue ();
837
+ assertThat (newOwner .name ()).isEqualTo ("foo" );
838
+ assertThat (newOwner .owner ().type ().fullyQualifiedName ()).isEqualTo ("org.foo.A" );
805
839
}
806
840
807
841
@ Test
@@ -1337,7 +1371,7 @@ void declaration_annotation_member() {
1337
1371
assertThat (cu .sema .declarations .get (m .methodBinding )).isSameAs (m );
1338
1372
}
1339
1373
1340
- @ ParameterizedTest (name = "[{index}] Type bindings of variable v should not be null in \" {0}\" " )
1374
+ @ ParameterizedTest (name = "[{index}] Type bindings of variable v should not be null in \" {0}\" " )
1341
1375
@ ValueSource (strings = {
1342
1376
"interface I { int v; }" , // primitive
1343
1377
"interface I<T> { I<String> v; }" , // parameterized
@@ -1634,19 +1668,19 @@ void nested() {
1634
1668
@ Test
1635
1669
void constructor_with_type_arguments () {
1636
1670
String source = """
1637
- class MyClass {
1638
- <T extends I> MyClass(T t) {}
1639
- <T extends J & I> MyClass(T t) {}
1640
- void foo(B b, C c) {
1641
- new<B>MyClass((I) b);
1642
- new<C>MyClass(c);
1643
- }
1671
+ class MyClass {
1672
+ <T extends I> MyClass(T t) {}
1673
+ <T extends J & I> MyClass(T t) {}
1674
+ void foo(B b, C c) {
1675
+ new<B>MyClass((I) b);
1676
+ new<C>MyClass(c);
1644
1677
}
1645
- interface I {}
1646
- interface J {}
1647
- class B implements I {}
1648
- class C implements I, J {}
1649
- """ ;
1678
+ }
1679
+ interface I {}
1680
+ interface J {}
1681
+ class B implements I {}
1682
+ class C implements I, J {}
1683
+ """ ;
1650
1684
1651
1685
JavaTree .CompilationUnitTreeImpl cu = test (source );
1652
1686
ClassTree c = (ClassTree ) cu .types ().get (0 );
@@ -1692,7 +1726,7 @@ void should_skip_implicit_break_statement() {
1692
1726
private CompilationUnit createAST (String source ) {
1693
1727
JavaVersion version = JParserConfig .MAXIMUM_SUPPORTED_JAVA_VERSION ;
1694
1728
ASTParser astParser = ASTParser .newParser (AST .getJLSLatest ());
1695
- Map <String , String > options = new HashMap <>(JavaCore .getOptions ());
1729
+ Map <String , String > options = new HashMap <>(JavaCore .getOptions ());
1696
1730
JavaCore .setComplianceOptions (version .effectiveJavaVersionAsString (), options );
1697
1731
options .put (JavaCore .COMPILER_PB_ENABLE_PREVIEW_FEATURES , "enabled" );
1698
1732
astParser .setCompilerOptions (options );
@@ -1737,22 +1771,22 @@ class InnerB extends C.InnerC {
1737
1771
@ Test
1738
1772
void inner_class_depending_on_outer_class_parametrized_type () {
1739
1773
final String source = """
1740
- class X<T> {
1741
- InnerClass innerClass;
1742
- class InnerClass {
1743
- T method() {
1744
- return null;
1745
- }
1746
- }
1747
- static void test() {
1748
- new X<Y>().innerClass.method().method1();
1774
+ class X<T> {
1775
+ InnerClass innerClass;
1776
+ class InnerClass {
1777
+ T method() {
1778
+ return null;
1749
1779
}
1750
1780
}
1751
- class Y {
1752
- void method1() {
1753
- }
1781
+ static void test() {
1782
+ new X<Y>().innerClass.method().method1();
1783
+ }
1784
+ }
1785
+ class Y {
1786
+ void method1() {
1754
1787
}
1755
- """ ;
1788
+ }
1789
+ """ ;
1756
1790
JavaTree .CompilationUnitTreeImpl cu = test (source );
1757
1791
ClassTree classX = (ClassTree ) cu .types ().get (0 );
1758
1792
MethodTreeImpl method = (MethodTreeImpl ) ((ClassTree ) classX .members ().get (1 )).members ().get (0 );
@@ -1788,7 +1822,7 @@ void warnings_are_detected() {
1788
1822
List <JWarning > castWarnings = cu .warnings (JWarning .Type .REDUNDANT_CAST );
1789
1823
assertThat (castWarnings ).hasSize (2 );
1790
1824
1791
- TypeCastTree typeCast = (TypeCastTree )((VariableTree )((MethodTree )(((ClassTree ) cu .types ().get (0 )).members ().get (0 ))).block ().body ().get (0 )).initializer ();
1825
+ TypeCastTree typeCast = (TypeCastTree ) ((VariableTree ) ((MethodTree ) (((ClassTree ) cu .types ().get (0 )).members ().get (0 ))).block ().body ().get (0 )).initializer ();
1792
1826
JWarning parentCastWarning = castWarnings .get (0 );
1793
1827
assertThat (parentCastWarning .message ()).isEqualTo ("Unnecessary cast from String to String" );
1794
1828
assertThat (parentCastWarning .syntaxTree ()).isEqualTo (typeCast );
@@ -1798,4 +1832,36 @@ void warnings_are_detected() {
1798
1832
assertThat (nestedCastWarning .message ()).isEqualTo ("Unnecessary cast from String to String" );
1799
1833
assertThat (nestedCastWarning .syntaxTree ()).isEqualTo (parenthesizedTree );
1800
1834
}
1835
+
1836
+ @ Test
1837
+ void test_variable_equals_in_lambda () {
1838
+ String source = """
1839
+ package org.foo;
1840
+ class A {
1841
+ void f1() {
1842
+ java.util.function.Consumer<String> a = p -> { System.out.println(p); };
1843
+ java.util.function.Consumer<String> c = p -> { System.out.println(p); };
1844
+ }
1845
+ void f2() {
1846
+ java.util.function.Consumer<String> b = p -> { System.out.println(p); };
1847
+ }
1848
+ }
1849
+ """ ;
1850
+ JavaTree .CompilationUnitTreeImpl cu = test (source );
1851
+ ClassTreeImpl c = (ClassTreeImpl ) cu .types ().get (0 );
1852
+ MethodTree f1 = (MethodTree ) c .members ().get (0 );
1853
+ MethodTree f2 = (MethodTree ) c .members ().get (1 );
1854
+ VariableTree variableTreeA = (VariableTree ) f1 .block ().body ().get (0 );
1855
+ VariableTree variableTreeC = (VariableTree ) f1 .block ().body ().get (1 );
1856
+ VariableTree variableTreeB = (VariableTree ) f2 .block ().body ().get (0 );
1857
+ LambdaExpressionTreeImpl lambdaA = (LambdaExpressionTreeImpl ) variableTreeA .initializer ();
1858
+ LambdaExpressionTreeImpl lambdaB = (LambdaExpressionTreeImpl ) variableTreeB .initializer ();
1859
+ LambdaExpressionTreeImpl lambdaC = (LambdaExpressionTreeImpl ) variableTreeC .initializer ();
1860
+ VariableTreeImpl pOfA = (VariableTreeImpl ) lambdaA .parameters ().get (0 );
1861
+ VariableTreeImpl pOfB = (VariableTreeImpl ) lambdaB .parameters ().get (0 );
1862
+ VariableTreeImpl pOfC = (VariableTreeImpl ) lambdaC .parameters ().get (0 );
1863
+
1864
+ assertThat (pOfA .symbol ()).isNotSameAs (pOfB .symbol ());
1865
+ assertThat (pOfA .symbol ()).isNotSameAs (pOfC .symbol ());
1866
+ }
1801
1867
}
0 commit comments