diff --git a/semanticdb/integration/src/main/scala/example/ForComprehension.scala b/semanticdb/integration/src/main/scala/example/ForComprehension.scala index 23cbc1ce9d..fcfe6636b5 100644 --- a/semanticdb/integration/src/main/scala/example/ForComprehension.scala +++ b/semanticdb/integration/src/main/scala/example/ForComprehension.scala @@ -42,4 +42,8 @@ class ForComprehension { f ) } + val x: Option[(Int, Int)] = None + for { + (_, _) <- x + } yield () } diff --git a/semanticdb/scalac/library/src/main/scala/scala/meta/internal/semanticdb/scalac/TextDocumentOps.scala b/semanticdb/scalac/library/src/main/scala/scala/meta/internal/semanticdb/scalac/TextDocumentOps.scala index 0870ef13e7..0e8f270daa 100644 --- a/semanticdb/scalac/library/src/main/scala/scala/meta/internal/semanticdb/scalac/TextDocumentOps.scala +++ b/semanticdb/scalac/library/src/main/scala/scala/meta/internal/semanticdb/scalac/TextDocumentOps.scala @@ -728,7 +728,15 @@ trait TextDocumentOps { self: SemanticdbOps => case _ => } case select: g.Select if isSyntheticName(select) => - tryFindMtree(select.qualifier) + select.qualifier match { + // This case handles multiple synthetics in a row, for example + // + // ```val foo: Option[(Int, Int)] = None + // for { (_, _) <- foo } yield ()``` + // where `for` expands to `foo.withFilter(...).map(...)` + case g.Apply(s: g.Select, _) if isSyntheticName(s) => traverse(s) + case _ => tryFindMtree(select.qualifier) + } tryFindSynthetic(select) case gtree: g.AppliedTypeTree => tryFindMtree(gtree) diff --git a/tests/jvm/src/test/resources/example/ForComprehension.scala b/tests/jvm/src/test/resources/example/ForComprehension.scala index 02967be5a1..e90f789779 100644 --- a/tests/jvm/src/test/resources/example/ForComprehension.scala +++ b/tests/jvm/src/test/resources/example/ForComprehension.scala @@ -42,4 +42,8 @@ class ForComprehension/*<=example.ForComprehension#*/ { f/*=>local15*/ ) } + val x/*<=example.ForComprehension#x.*/: Option/*=>scala.Option#*/[(Int/*=>scala.Int#*/, Int/*=>scala.Int#*/)] = None/*=>scala.None.*/ + for { + (_, _) <- x/*=>example.ForComprehension#x.*/ + } yield () } diff --git a/tests/jvm/src/test/resources/metac.expect_2.12 b/tests/jvm/src/test/resources/metac.expect_2.12 index a3c6dcbbc7..78ebd6f32f 100644 --- a/tests/jvm/src/test/resources/metac.expect_2.12 +++ b/tests/jvm/src/test/resources/metac.expect_2.12 @@ -1461,14 +1461,18 @@ Schema => SemanticDB v4 Uri => semanticdb/integration/src/main/scala/example/ForComprehension.scala Text => non-empty Language => Scala -Symbols => 13 entries -Occurrences => 50 entries -Synthetics => 12 entries +Symbols => 15 entries +Occurrences => 56 entries +Synthetics => 13 entries Symbols: -example/ForComprehension# => class ForComprehension extends AnyRef { +1 decls } +example/ForComprehension# => class ForComprehension extends AnyRef { +2 decls } AnyRef => scala/AnyRef# example/ForComprehension#``(). => primary ctor () +example/ForComprehension#x. => val method x: Option[Tuple2[Int, Int]] + Option => scala/Option# + Tuple2 => scala/Tuple2# + Int => scala/Int# local0 => param a: Int Int => scala/Int# local1 => val local b: Int @@ -1495,6 +1499,9 @@ local14 => val local e: Tuple4[Int, Int, Int, Int] local15 => param f: Tuple4[Int, Int, Int, Int] Tuple4 => scala/Tuple4# Int => scala/Int# +local16 => param check$ifrefutable$2: Tuple2[Int, Int] + Tuple2 => scala/Tuple2# + Int => scala/Int# Occurrences: [0:8..0:15): example <= example/ @@ -1547,6 +1554,12 @@ Occurrences: [39:6..39:7): d => local12 [40:6..40:7): e => local14 [41:6..41:7): f => local15 +[44:6..44:7): x <= example/ForComprehension#x. +[44:9..44:15): Option => scala/Option# +[44:17..44:20): Int => scala/Int# +[44:22..44:25): Int => scala/Int# +[44:30..44:34): None => scala/None. +[46:14..46:15): x => example/ForComprehension#x. Synthetics: [3:2..8:19): for { @@ -1715,6 +1728,15 @@ Synthetics: apply => scala/collection/immutable/List.apply(). Tuple4 => scala/Tuple4# Int => scala/Int# +[45:2..47:12): for { + (_, _) <- x + } yield () => orig(x).withFilter({(check$ifrefutable$2) => orig()}).map[Unit]({(local17) => orig((_, _) <- x + } yield ())}) + withFilter => scala/Option#withFilter(). + check$ifrefutable$2 => local16 + map => scala/Option#WithFilter#map(). + Unit => scala/Unit# + local17 => local17 semanticdb/integration/src/main/scala/example/ImplicitConversion.scala ---------------------------------------------------------------------- diff --git a/tests/jvm/src/test/resources/metac.expect_2.13 b/tests/jvm/src/test/resources/metac.expect_2.13 index 0c0ebefd30..2842bdeff4 100644 --- a/tests/jvm/src/test/resources/metac.expect_2.13 +++ b/tests/jvm/src/test/resources/metac.expect_2.13 @@ -1485,14 +1485,18 @@ Schema => SemanticDB v4 Uri => semanticdb/integration/src/main/scala/example/ForComprehension.scala Text => non-empty Language => Scala -Symbols => 13 entries -Occurrences => 50 entries -Synthetics => 12 entries +Symbols => 15 entries +Occurrences => 56 entries +Synthetics => 13 entries Symbols: -example/ForComprehension# => class ForComprehension extends AnyRef { +1 decls } +example/ForComprehension# => class ForComprehension extends AnyRef { +2 decls } AnyRef => scala/AnyRef# example/ForComprehension#``(). => primary ctor () +example/ForComprehension#x. => val method x: Option[Tuple2[Int, Int]] + Option => scala/Option# + Tuple2 => scala/Tuple2# + Int => scala/Int# local0 => param a: Int Int => scala/Int# local1 => val local b: Int @@ -1519,6 +1523,9 @@ local14 => val local e: Tuple4[Int, Int, Int, Int] local15 => param f: Tuple4[Int, Int, Int, Int] Tuple4 => scala/Tuple4# Int => scala/Int# +local16 => param check$ifrefutable$2: Tuple2[Int, Int] + Tuple2 => scala/Tuple2# + Int => scala/Int# Occurrences: [0:8..0:15): example <= example/ @@ -1571,6 +1578,12 @@ Occurrences: [39:6..39:7): d => local12 [40:6..40:7): e => local14 [41:6..41:7): f => local15 +[44:6..44:7): x <= example/ForComprehension#x. +[44:9..44:15): Option => scala/Option# +[44:17..44:20): Int => scala/Int# +[44:22..44:25): Int => scala/Int# +[44:30..44:34): None => scala/None. +[46:14..46:15): x => example/ForComprehension#x. Synthetics: [3:2..8:19): for { @@ -1730,6 +1743,15 @@ Synthetics: apply => scala/collection/IterableFactory#apply(). Tuple4 => scala/Tuple4# Int => scala/Int# +[45:2..47:12): for { + (_, _) <- x + } yield () => orig(x).withFilter({(check$ifrefutable$2) => orig()}).map[Unit]({(local17) => orig((_, _) <- x + } yield ())}) + withFilter => scala/Option#withFilter(). + check$ifrefutable$2 => local16 + map => scala/Option#WithFilter#map(). + Unit => scala/Unit# + local17 => local17 semanticdb/integration/src/main/scala/example/ImplicitConversion.scala ---------------------------------------------------------------------- diff --git a/tests/jvm/src/test/resources/metacp.expect_2.12 b/tests/jvm/src/test/resources/metacp.expect_2.12 index 4b7b54a4eb..95adfbbde1 100644 --- a/tests/jvm/src/test/resources/metacp.expect_2.12 +++ b/tests/jvm/src/test/resources/metacp.expect_2.12 @@ -1764,12 +1764,16 @@ Schema => SemanticDB v4 Uri => example/ForComprehension.class Text => empty Language => Scala -Symbols => 2 entries +Symbols => 3 entries Symbols: -example/ForComprehension# => class ForComprehension extends AnyRef { +1 decls } +example/ForComprehension# => class ForComprehension extends AnyRef { +2 decls } AnyRef => scala/AnyRef# example/ForComprehension#``(). => primary ctor () +example/ForComprehension#x. => val method x: Option[Tuple2[Int, Int]] + Option => scala/Option# + Tuple2 => scala/Tuple2# + Int => scala/Int# example/ImplicitConversion.class -------------------------------- diff --git a/tests/jvm/src/test/resources/metacp.expect_2.13 b/tests/jvm/src/test/resources/metacp.expect_2.13 index 4c9148d7f6..b98b9b1047 100644 --- a/tests/jvm/src/test/resources/metacp.expect_2.13 +++ b/tests/jvm/src/test/resources/metacp.expect_2.13 @@ -1781,12 +1781,16 @@ Schema => SemanticDB v4 Uri => example/ForComprehension.class Text => empty Language => Scala -Symbols => 2 entries +Symbols => 3 entries Symbols: -example/ForComprehension# => class ForComprehension extends AnyRef { +1 decls } +example/ForComprehension# => class ForComprehension extends AnyRef { +2 decls } AnyRef => scala/AnyRef# example/ForComprehension#``(). => primary ctor () +example/ForComprehension#x. => val method x: Option[Tuple2[Int, Int]] + Option => scala/Option# + Tuple2 => scala/Tuple2# + Int => scala/Int# example/ImplicitConversion.class -------------------------------- diff --git a/tests/jvm/src/test/scala/scala/meta/tests/semanticdb/TargetedSuite.scala b/tests/jvm/src/test/scala/scala/meta/tests/semanticdb/TargetedSuite.scala index ca02f49d05..90eb007e60 100644 --- a/tests/jvm/src/test/scala/scala/meta/tests/semanticdb/TargetedSuite.scala +++ b/tests/jvm/src/test/scala/scala/meta/tests/semanticdb/TargetedSuite.scala @@ -225,4 +225,21 @@ class TargetedSuite extends SemanticdbSuite { assertEquals(toInt, "scala/Int#toLong().") } ) + + targeted( + """ + package n + | object ForCompWithFilter { + | val foo: Option[(Int, Int)] = None + | for { + | (_, _) <- <> + | (_, _) <- <> + | } yield () + |} + """.stripMargin, + (_, foo1, foo2) => { + assertEquals(foo1, "n/ForCompWithFilter.foo.") + assertEquals(foo2, "n/ForCompWithFilter.foo.") + } + ) }