From bf7b455995bd5b43ba573ec81f52383cd8df4884 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Wed, 27 Oct 2021 16:46:19 +0200 Subject: [PATCH 1/2] Navigate the AST within AnnotatedType and ImportType Related to https://github.com/lampepfl/dotty/issues/13624 --- .../dotty/tools/dotc/ast/NavigateAST.scala | 23 ++++++++++++++++++- .../tools/languageserver/CompletionTest.scala | 19 ++++++++++++++- .../tools/languageserver/HoverTest.scala | 8 +++++-- 3 files changed, 46 insertions(+), 4 deletions(-) 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..26b5d51993b9 100644 --- a/language-server/test/dotty/tools/languageserver/CompletionTest.scala +++ b/language-server/test/dotty/tools/languageserver/CompletionTest.scala @@ -895,4 +895,21 @@ class CompletionTest { @Test def i12465_hkt_alias: Unit = code"""???.asInstanceOf[Seq].${m1}""".withSource .completion(m1, Set()) -} + + @Test def i13624_annotType: Unit = + code"""|class MyAnnotation extends annotation.StaticAnnotation + |val x = 1: @MyAnnot${m1} + |type X = Int @MyAnnot${m2}""".withSource + .completion( + m1, + Set( + ("MyAnnotation", Class, "MyAnnotation"), + ("MyAnnotation", Module, "MyAnnotation") + ) + ).completion( + m2, + Set( + ("MyAnnotation", Class, "MyAnnotation"), + ("MyAnnotation", Module, "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 = { From 0fec7808dbe15edc198ba84cc3f4c94f81945da2 Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Thu, 28 Oct 2021 18:54:07 +0200 Subject: [PATCH 2/2] Add additional test for annotation completions --- .../tools/languageserver/CompletionTest.scala | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/language-server/test/dotty/tools/languageserver/CompletionTest.scala b/language-server/test/dotty/tools/languageserver/CompletionTest.scala index 26b5d51993b9..1dd9516de7d1 100644 --- a/language-server/test/dotty/tools/languageserver/CompletionTest.scala +++ b/language-server/test/dotty/tools/languageserver/CompletionTest.scala @@ -897,9 +897,18 @@ class CompletionTest { .completion(m1, Set()) @Test def i13624_annotType: Unit = - code"""|class MyAnnotation extends annotation.StaticAnnotation + 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}""".withSource + |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( @@ -912,4 +921,29 @@ class CompletionTest { ("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") + ) + ) +}