diff --git a/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala b/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala index ffc7d04faa52..61561d5eaa24 100644 --- a/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala +++ b/compiler/src/dotty/tools/dotc/ast/NavigateAST.scala @@ -5,6 +5,10 @@ import core.Contexts._ import core.Decorators._ import util.Spans._ import Trees.{MemberDef, DefTree, WithLazyField} +import dotty.tools.dotc.core.Annotations.ConcreteAnnotation +import dotty.tools.dotc.core.Types.AnnotatedType +import dotty.tools.dotc.core.Types.ImportType +import dotty.tools.dotc.core.Types.Type /** Utility functions to go from typed to untyped ASTs */ // TODO: Handle trees with mixed source files @@ -86,6 +90,18 @@ object NavigateAST { } bestFit } + /* + * Annotations trees are located in the Type + */ + def unpackAnnotations(t: Type, path: List[Positioned]): List[Positioned] = + t match { + case ann: AnnotatedType => + unpackAnnotations(ann.parent, childPath(ann.annot.tree.productIterator, path)) + case imp: ImportType => + childPath(imp.expr.productIterator, path) + case other => + path + } def singlePath(p: Positioned, path: List[Positioned]): List[Positioned] = if (p.span.exists && !(skipZeroExtent && p.span.isZeroExtent) && p.span.contains(span)) { // FIXME: We shouldn't be manually forcing trees here, we should replace @@ -98,7 +114,12 @@ object NavigateAST { } childPath(p.productIterator, p :: path) } - else path + else { + p match { + case t: untpd.TypeTree => unpackAnnotations(t.typeOpt, path) + case _ => path + } + } singlePath(from, Nil) } } diff --git a/language-server/test/dotty/tools/languageserver/CompletionTest.scala b/language-server/test/dotty/tools/languageserver/CompletionTest.scala index 7e71c0a4c2b1..1dd9516de7d1 100644 --- a/language-server/test/dotty/tools/languageserver/CompletionTest.scala +++ b/language-server/test/dotty/tools/languageserver/CompletionTest.scala @@ -895,4 +895,55 @@ class CompletionTest { @Test def i12465_hkt_alias: Unit = code"""???.asInstanceOf[Seq].${m1}""".withSource .completion(m1, Set()) + + @Test def i13624_annotType: Unit = + code"""|object Foo{ + | class MyAnnotation extends annotation.StaticAnnotation + |} + |class MyAnnotation extends annotation.StaticAnnotation + |class Annotation2(a: String) extends annotation.StaticAnnotation + |val x = 1: @MyAnnot${m1} + |type X = Int @MyAnnot${m2} + |val y = 1: @Foo.MyAnnot${m3} + |val z = 1: @Foo.MyAnnotation @MyAnno${m4} + |type Y = Int @MyAnnotation @Foo.MyAnnota${m5} + |val w = 1: @Annotation2("abc": @Foo.MyAnnot${m6}) + |""".withSource + .completion( + m1, + Set( + ("MyAnnotation", Class, "MyAnnotation"), + ("MyAnnotation", Module, "MyAnnotation") + ) + ).completion( + m2, + Set( + ("MyAnnotation", Class, "MyAnnotation"), + ("MyAnnotation", Module, "MyAnnotation") + ) + ).completion( + m3, + Set( + ("MyAnnotation", Class, "Foo.MyAnnotation"), + ("MyAnnotation", Module, "Foo.MyAnnotation") + ) + ).completion( + m4, + Set( + ("MyAnnotation", Class, "MyAnnotation"), + ("MyAnnotation", Module, "MyAnnotation") + ) + ).completion( + m5, + Set( + ("MyAnnotation", Class, "Foo.MyAnnotation"), + ("MyAnnotation", Module, "Foo.MyAnnotation") + ) + ).completion( + m6, + Set( + ("MyAnnotation", Class, "Foo.MyAnnotation"), + ("MyAnnotation", Module, "Foo.MyAnnotation") + ) + ) } diff --git a/language-server/test/dotty/tools/languageserver/HoverTest.scala b/language-server/test/dotty/tools/languageserver/HoverTest.scala index 54d3271f2565..4309b0aeeea0 100644 --- a/language-server/test/dotty/tools/languageserver/HoverTest.scala +++ b/language-server/test/dotty/tools/languageserver/HoverTest.scala @@ -177,7 +177,7 @@ class HoverTest { @Test def i4678: Unit = { code"""class Foo { - | val x: Int = (${m1}1:${m2} ${m3}@annot1 @annot2 @annot3 @annot4 @annot5${m4}) + | val x: Int = (${m1}1:${m2} ${m3}@annot1${m4} ${m5}@annot2${m6} ${m7}@annot3${m8} ${m9}@annot4${m10} ${m11}@annot5${m12}) |} |class annot1 extends scala.annotation.Annotation |class annot2 extends scala.annotation.Annotation @@ -186,7 +186,11 @@ class HoverTest { |class annot5 extends scala.annotation.Annotation |""".withSource .hover(m1 to m2, hoverContent("(1 : Int)")) - .hover(m3 to m4, hoverContent("(1 : Int) @annot1 @annot2 @annot3 @annot4 @annot5")) + .hover(m3 to m4, hoverContent("annot1")) + .hover(m5 to m6, hoverContent("annot2")) + .hover(m7 to m8, hoverContent("annot3")) + .hover(m9 to m10, hoverContent("annot4")) + .hover(m11 to m12, hoverContent("annot5")) } @Test def unicodeChar: Unit = {