Skip to content

Retain position of extension function calls #11574

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,18 @@ object Trees {
qualifier.typeOpt.member(name).atSignature(Signature.NotAMethod, name)
case _ =>
super.denot

def nameSpan(using Context): Span =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this which did not need any attachments (I don't think its that important to do the point span for synthetic):

def nameSpan(using Context): Span =
  if span.exists then
    val point = span.point
    if name.toTermName == nme.ERROR then Span(point)
    else if qualifier.span.start > span.start then // right associative
      val realName = name.stripModuleClassSuffix.lastPart
      Span(span.start, span.start + realName.length, point)
    else
      Span(point, span.end, point)
  else span

if span.exists then
val point = span.point
if name.toTermName == nme.ERROR then
Span(point)
else if qualifier.span.start > span.start then // right associative
val realName = name.stripModuleClassSuffix.lastPart
Span(span.start, span.start + realName.length, point)
else
Span(point, span.end, point)
else span
}

class SelectWithSig[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name, val sig: Signature)(implicit @constructorOnly src: SourceFile)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2988,7 +2988,7 @@ class Typer extends Namer
def tryExtension(using Context): Tree =
findRef(tree.name, WildcardType, ExtensionMethod, EmptyFlags, qual.srcPos) match
case ref: TermRef =>
extMethodApply(untpd.ref(ref).withSpan(tree.span), qual, pt)
extMethodApply(untpd.TypedSplice(tpd.ref(ref).withSpan(tree.nameSpan)), qual, pt)
case _ =>
EmptyTree

Expand Down
2 changes: 1 addition & 1 deletion tests/semanticdb/expect/Enums.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ object Enums/*<-_empty_::Enums.*/:
extension [A/*<-_empty_::Enums.unwrap().[A]*/, B/*<-_empty_::Enums.unwrap().[B]*/](opt/*<-_empty_::Enums.unwrap().(opt)*/: Option/*->scala::Option#*/[A/*->_empty_::Enums.unwrap().[A]*/]) def unwrap/*<-_empty_::Enums.unwrap().*/(using ev/*<-_empty_::Enums.unwrap().(ev)*/: A/*->_empty_::Enums.unwrap().[A]*/ <:</*->_empty_::Enums.`<:<`#*/ Option/*->scala::Option#*/[B/*->_empty_::Enums.unwrap().[B]*/]): Option/*->scala::Option#*/[B/*->_empty_::Enums.unwrap().[B]*/] = ev/*->_empty_::Enums.unwrap().(ev)*/ match
case Refl/*->_empty_::Enums.`<:<`.Refl.*//*->_empty_::Enums.`<:<`.Refl.unapply().*/() => opt/*->_empty_::Enums.unwrap().(opt)*/.flatMap/*->scala::Option#flatMap().*/(identity/*->scala::Predef.identity().*//*->local0*/[Option/*->scala::Option#*/[B/*->_empty_::Enums.unwrap().[B]*/]])

val some1/*<-_empty_::Enums.some1.*/ = /*->_empty_::Enums.unwrap().*/Some/*->scala::Some.*//*->scala::Some.apply().*/(Some/*->scala::Some.*//*->scala::Some.apply().*/(1)).unwrap/*->_empty_::Enums.`<:<`.given_T().*/
val some1/*<-_empty_::Enums.some1.*/ = Some/*->scala::Some.*//*->scala::Some.apply().*/(Some/*->scala::Some.*//*->scala::Some.apply().*/(1)).unwrap/*->_empty_::Enums.unwrap().*//*->_empty_::Enums.`<:<`.given_T().*/

enum Planet/*<-_empty_::Enums.Planet#*/(mass/*<-_empty_::Enums.Planet#mass.*/: Double/*->scala::Double#*/, radius/*<-_empty_::Enums.Planet#radius.*/: Double/*->scala::Double#*/) extends Enum/*->java::lang::Enum#*/[Planet/*->_empty_::Enums.Planet#*/]/*->java::lang::Enum#`<init>`().*/:
private final val G/*<-_empty_::Enums.Planet#G.*/ = 6.67300E-11
Expand Down
9 changes: 9 additions & 0 deletions tests/semanticdb/expect/Extension.expect.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ext

/*<-ext::Extension$package.*/extension (s/*<-ext::Extension$package.foo().(s)*//*<-ext::Extension$package.`#*#`().(s)*/: String/*->scala::Predef.String#*/)
def foo/*<-ext::Extension$package.foo().*/: Int/*->scala::Int#*/ = 42
def #*#/*<-ext::Extension$package.`#*#`().*/ (i/*<-ext::Extension$package.`#*#`().(i)*/: Int/*->scala::Int#*/): (String/*->scala::Predef.String#*/, Int/*->scala::Int#*/) = (/*->scala::Tuple2.apply().*/s/*->ext::Extension$package.`#*#`().(s)*/, i/*->ext::Extension$package.`#*#`().(i)*/)

val a/*<-ext::Extension$package.a.*/ = "asd".foo/*->ext::Extension$package.foo().*/

val c/*<-ext::Extension$package.c.*/ = "foo" #*#/*->ext::Extension$package.`#*#`().*/ 23
9 changes: 9 additions & 0 deletions tests/semanticdb/expect/Extension.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ext

extension (s: String)
def foo: Int = 42
def #*# (i: Int): (String, Int) = (s, i)

val a = "asd".foo

val c = "foo" #*# 23
6 changes: 3 additions & 3 deletions tests/semanticdb/expect/Givens.expect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ object Givens/*<-a::b::Givens.*/:
def sayGoodbye/*<-a::b::Givens.sayGoodbye().*/ = s"/*->scala::StringContext.apply().*/Goodbye, from $any/*->a::b::Givens.sayGoodbye().(any)*/"/*->scala::StringContext#s().*/
def saySoLong/*<-a::b::Givens.saySoLong().*/ = s"/*->scala::StringContext.apply().*/So Long, from $any/*->a::b::Givens.saySoLong().(any)*/"/*->scala::StringContext#s().*/

val hello1/*<-a::b::Givens.hello1.*/ = /*->a::b::Givens.sayHello().*/1.sayHello
val goodbye1/*<-a::b::Givens.goodbye1.*/ = /*->a::b::Givens.sayGoodbye().*/1.sayGoodbye
val soLong1/*<-a::b::Givens.soLong1.*/ = /*->a::b::Givens.saySoLong().*/1.saySoLong
val hello1/*<-a::b::Givens.hello1.*/ = 1.sayHello/*->a::b::Givens.sayHello().*/
val goodbye1/*<-a::b::Givens.goodbye1.*/ = 1.sayGoodbye/*->a::b::Givens.sayGoodbye().*/
val soLong1/*<-a::b::Givens.soLong1.*/ = 1.saySoLong/*->a::b::Givens.saySoLong().*/

trait Monoid/*<-a::b::Givens.Monoid#*/[A/*<-a::b::Givens.Monoid#[A]*/]:
def empty/*<-a::b::Givens.Monoid#empty().*/: A/*->a::b::Givens.Monoid#[A]*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package ext

/*<-ext::RightAssociativeExtension$package.*/extension (s/*<-ext::RightAssociativeExtension$package.`:*:`().(s)*/: String/*->scala::Predef.String#*/)
def :*:/*<-ext::RightAssociativeExtension$package.`:*:`().*/ (i/*<-ext::RightAssociativeExtension$package.`:*:`().(i)*/: Int/*->scala::Int#*/): (String/*->scala::Predef.String#*/, Int/*->scala::Int#*/) = (/*->scala::Tuple2.apply().*/s/*->ext::RightAssociativeExtension$package.`:*:`().(s)*/, i/*->ext::RightAssociativeExtension$package.`:*:`().(i)*/)

val b/*<-ext::RightAssociativeExtension$package.b.*/ = "foo" :*:/*->ext::RightAssociativeExtension$package.`:*:`().*/ 23
6 changes: 6 additions & 0 deletions tests/semanticdb/expect/RightAssociativeExtension.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package ext

extension (s: String)
def :*: (i: Int): (String, Int) = (s, i)

val b = "foo" :*: 23
84 changes: 80 additions & 4 deletions tests/semanticdb/metac.expect
Original file line number Diff line number Diff line change
Expand Up @@ -966,11 +966,11 @@ Occurrences:
[52:40..52:46): Option -> scala/Option#
[52:47..52:48): B -> _empty_/Enums.unwrap().[B]
[54:6..54:11): some1 <- _empty_/Enums.some1.
[54:14..54:14): -> _empty_/Enums.unwrap().
[54:14..54:18): Some -> scala/Some.
[54:18..54:18): -> scala/Some.apply().
[54:19..54:23): Some -> scala/Some.
[54:23..54:23): -> scala/Some.apply().
[54:28..54:34): unwrap -> _empty_/Enums.unwrap().
[54:34..54:34): -> _empty_/Enums.`<:<`.given_T().
[56:7..56:13): Planet <- _empty_/Enums.Planet#
[56:13..56:13): <- _empty_/Enums.Planet#`<init>`().
Expand Down Expand Up @@ -1104,6 +1104,48 @@ Occurrences:
[9:33..9:36): Int -> scala/Int#
[9:37..9:37): -> scala/reflect/ClassTag.apply().

expect/Extension.scala
----------------------

Summary:
Schema => SemanticDB v4
Uri => Extension.scala
Text => empty
Language => Scala
Symbols => 8 entries
Occurrences => 19 entries

Symbols:
ext/Extension$package. => final package object ext
ext/Extension$package.`#*#`(). => method #*#
ext/Extension$package.`#*#`().(i) => param i
ext/Extension$package.`#*#`().(s) => param s
ext/Extension$package.a. => val method a
ext/Extension$package.c. => val method c
ext/Extension$package.foo(). => method foo
ext/Extension$package.foo().(s) => param s

Occurrences:
[0:8..0:11): ext <- ext/
[2:0..2:0): <- ext/Extension$package.
[2:11..2:12): s <- ext/Extension$package.foo().(s)
[2:11..2:12): s <- ext/Extension$package.`#*#`().(s)
[2:14..2:20): String -> scala/Predef.String#
[3:6..3:9): foo <- ext/Extension$package.foo().
[3:11..3:14): Int -> scala/Int#
[4:6..4:9): #*# <- ext/Extension$package.`#*#`().
[4:11..4:12): i <- ext/Extension$package.`#*#`().(i)
[4:14..4:17): Int -> scala/Int#
[4:21..4:27): String -> scala/Predef.String#
[4:29..4:32): Int -> scala/Int#
[4:37..4:37): -> scala/Tuple2.apply().
[4:37..4:38): s -> ext/Extension$package.`#*#`().(s)
[4:40..4:41): i -> ext/Extension$package.`#*#`().(i)
[6:4..6:5): a <- ext/Extension$package.a.
[6:14..6:17): foo -> ext/Extension$package.foo().
[8:4..8:5): c <- ext/Extension$package.c.
[8:14..8:17): #*# -> ext/Extension$package.`#*#`().

expect/ForComprehension.scala
-----------------------------

Expand Down Expand Up @@ -1288,11 +1330,11 @@ Occurrences:
[10:37..10:40): any -> a/b/Givens.saySoLong().(any)
[10:40..10:41): " -> scala/StringContext#s().
[12:6..12:12): hello1 <- a/b/Givens.hello1.
[12:15..12:15): -> a/b/Givens.sayHello().
[12:17..12:25): sayHello -> a/b/Givens.sayHello().
[13:6..13:14): goodbye1 <- a/b/Givens.goodbye1.
[13:17..13:17): -> a/b/Givens.sayGoodbye().
[13:19..13:29): sayGoodbye -> a/b/Givens.sayGoodbye().
[14:6..14:13): soLong1 <- a/b/Givens.soLong1.
[14:16..14:16): -> a/b/Givens.saySoLong().
[14:18..14:27): saySoLong -> a/b/Givens.saySoLong().
[16:8..16:14): Monoid <- a/b/Givens.Monoid#
[16:14..16:14): <- a/b/Givens.Monoid#`<init>`().
[16:15..16:16): A <- a/b/Givens.Monoid#[A]
Expand Down Expand Up @@ -2388,6 +2430,40 @@ Occurrences:
[31:10..31:11): T -> prefixes/M.T#
[31:14..31:17): ??? -> scala/Predef.`???`().

expect/RightAssociativeExtension.scala
--------------------------------------

Summary:
Schema => SemanticDB v4
Uri => RightAssociativeExtension.scala
Text => empty
Language => Scala
Symbols => 5 entries
Occurrences => 14 entries

Symbols:
ext/RightAssociativeExtension$package. => final package object ext
ext/RightAssociativeExtension$package.`:*:`(). => method :*:
ext/RightAssociativeExtension$package.`:*:`().(i) => param i
ext/RightAssociativeExtension$package.`:*:`().(s) => param s
ext/RightAssociativeExtension$package.b. => val method b

Occurrences:
[0:8..0:11): ext <- ext/
[2:0..2:0): <- ext/RightAssociativeExtension$package.
[2:11..2:12): s <- ext/RightAssociativeExtension$package.`:*:`().(s)
[2:14..2:20): String -> scala/Predef.String#
[3:6..3:9): :*: <- ext/RightAssociativeExtension$package.`:*:`().
[3:11..3:12): i <- ext/RightAssociativeExtension$package.`:*:`().(i)
[3:14..3:17): Int -> scala/Int#
[3:21..3:27): String -> scala/Predef.String#
[3:29..3:32): Int -> scala/Int#
[3:37..3:37): -> scala/Tuple2.apply().
[3:37..3:38): s -> ext/RightAssociativeExtension$package.`:*:`().(s)
[3:40..3:41): i -> ext/RightAssociativeExtension$package.`:*:`().(i)
[5:4..5:5): b <- ext/RightAssociativeExtension$package.b.
[5:14..5:17): :*: -> ext/RightAssociativeExtension$package.`:*:`().

expect/Selfs.scala
------------------

Expand Down