diff --git a/compiler/src/dotty/tools/dotc/interactive/Completion.scala b/compiler/src/dotty/tools/dotc/interactive/Completion.scala index 146040f4ce3e..af3cf679c161 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Completion.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Completion.scala @@ -16,13 +16,14 @@ import dotty.tools.dotc.core.Symbols.{Symbol, defn} import dotty.tools.dotc.core.StdNames.nme import dotty.tools.dotc.core.SymDenotations.SymDenotation import dotty.tools.dotc.core.TypeError -import dotty.tools.dotc.core.Types.{ExprType, MethodOrPoly, NameFilter, NoType, TermRef, Type} +import dotty.tools.dotc.core.Types.{AppliedType, ExprType, MethodOrPoly, NameFilter, NoType, TermRef, Type} import dotty.tools.dotc.parsing.Tokens import dotty.tools.dotc.util.Chars import dotty.tools.dotc.util.SourcePosition import scala.collection.mutable import scala.util.control.NonFatal +import dotty.tools.dotc.core.Types.TypeRef /** * One of the results of a completion query. @@ -310,10 +311,12 @@ object Completion { resultMappings } - /** Replaces underlying type with reduced one, when it's MatchType */ - def reduceUnderlyingMatchType(qual: Tree)(using Context): Tree= - qual.tpe.widen match - case ctx.typer.MatchTypeInDisguise(mt) => qual.withType(mt) + /** Widen only those types which are applied or are exactly nothing + */ + def widenQualifier(qual: Tree)(using Context): Tree = + qual.tpe.widenDealias match + case widenedType if widenedType.isExactlyNothing => qual.withType(widenedType) + case appliedType: AppliedType => qual.withType(appliedType) case _ => qual /** Completions for selections from a term. @@ -321,17 +324,17 @@ object Completion { * and so do members from extensions over members from implicit conversions */ def selectionCompletions(qual: Tree)(using Context): CompletionMap = - val reducedQual = reduceUnderlyingMatchType(qual) + val adjustedQual = widenQualifier(qual) - implicitConversionMemberCompletions(reducedQual) ++ - extensionCompletions(reducedQual) ++ - directMemberCompletions(reducedQual) + implicitConversionMemberCompletions(adjustedQual) ++ + extensionCompletions(adjustedQual) ++ + directMemberCompletions(adjustedQual) /** Completions for members of `qual`'s type. * These include inherited definitions but not members added by extensions or implicit conversions */ def directMemberCompletions(qual: Tree)(using Context): CompletionMap = - if qual.tpe.widenDealias.isExactlyNothing then + if qual.tpe.isExactlyNothing then Map.empty else accessibleMembers(qual.tpe).groupByName @@ -378,7 +381,7 @@ object Completion { /** Completions from implicit conversions including old style extensions using implicit classes */ private def implicitConversionMemberCompletions(qual: Tree)(using Context): CompletionMap = - if qual.tpe.widenDealias.isExactlyNothing || qual.tpe.isNullType then + if qual.tpe.isExactlyNothing || qual.tpe.isNullType then Map.empty else val membersFromConversion = diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 0af8ee8dc624..c815b85170e4 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1522,22 +1522,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer assignType(cpy.Closure(tree)(env1, meth1, target), meth1, target) } - /** Extractor for match types hidden behind an AppliedType/MatchAlias */ - object MatchTypeInDisguise { - def unapply(tp: AppliedType)(using Context): Option[MatchType] = tp match { - case AppliedType(tycon: TypeRef, args) => - tycon.info match { - case MatchAlias(alias) => - alias.applyIfParameterized(args) match { - case mt: MatchType => Some(mt) - case _ => None - } - case _ => None - } - case _ => None - } - } - def typedMatch(tree: untpd.Match, pt: Type)(using Context): Tree = tree.selector match { case EmptyTree => @@ -1565,6 +1549,21 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val selType = rawSelectorTpe match case c: ConstantType if tree.isInline => c case otherTpe => otherTpe.widen + /** Extractor for match types hidden behind an AppliedType/MatchAlias */ + object MatchTypeInDisguise { + def unapply(tp: AppliedType)(using Context): Option[MatchType] = tp match { + case AppliedType(tycon: TypeRef, args) => + tycon.info match { + case MatchAlias(alias) => + alias.applyIfParameterized(args) match { + case mt: MatchType => Some(mt) + case _ => None + } + case _ => None + } + case _ => None + } + } /** Does `tree` has the same shape as the given match type? * We only support typed patterns with empty guards, but diff --git a/language-server/test/dotty/tools/languageserver/CompletionTest.scala b/language-server/test/dotty/tools/languageserver/CompletionTest.scala index b97b343e0791..757ac736b6fa 100644 --- a/language-server/test/dotty/tools/languageserver/CompletionTest.scala +++ b/language-server/test/dotty/tools/languageserver/CompletionTest.scala @@ -5,53 +5,58 @@ import org.junit.Test import org.eclipse.lsp4j.CompletionItemKind._ import dotty.tools.languageserver.util.Code._ +import dotty.tools.languageserver.util.CodeTester import dotty.tools.languageserver.util.actions.CodeCompletion class CompletionTest { @Test def completion0: Unit = { - code"class Foo { val xyz: Int = 0; def y: Int = xy${m1} }".withSource - .completion(m1, Set(("xyz", Field, "Int"))) + code"class Foo { val xyz: Int = 0; def y: Int = xy${m1} }" + .completion(("xyz", Field, "Int")) } @Test def completionFromScalaPredef: Unit = { - code"class Foo { def foo: Unit = prin${m1} }".withSource - .completion(m1, Set( + code"class Foo { def foo: Unit = prin${m1} }" + .completion( ("print", Method, "(x: Any): Unit"), ("printf", Method, "(text: String, xs: Any*): Unit"), ("println", Method, "(x: Any): Unit"), - ("println", Method, "(): Unit") - )) + ("println", Method, "(): Unit"), + ) } @Test def completionFromNewScalaPredef: Unit = { - code"class Foo { val foo = summ${m1} }".withSource - .completion(m1, Set(("summon", Method, "[T](using x: T): x.type"))) + code"class Foo { val foo = summ${m1} }" + .completion(("summon", Method, "[T](using x: T): x.type")) } @Test def completionFromScalaPackage: Unit = { - code"class Foo { val foo: Conv${m1} }".withSource - .completion(m1, Set(("Conversion", Class, "scala.Conversion"))) + code"class Foo { val foo: Conv${m1} }" + .completion(("Conversion", Class, "scala.Conversion")) } @Test def completionFromScalaPackageObject: Unit = { - code"class Foo { val foo: BigD${m1} }".withSource - .completion(m1, Set(("BigDecimal", Field, "scala.BigDecimal"), - ("BigDecimal", Method, "=> math.BigDecimal.type"))) + code"class Foo { val foo: BigD${m1} }" + .completion( + ("BigDecimal", Field, "scala.BigDecimal"), + ("BigDecimal", Method, "=> math.BigDecimal.type"), + ) } @Test def completionFromSyntheticPackageObject: Unit = { - code"class Foo { val foo: IArr${m1} }".withSource - .completion(m1, Set(("IArray", Module, "IArray"), - ("IArray", Field, "scala.IArray"))) + code"class Foo { val foo: IArr${m1} }" + .completion( + ("IArray", Module, "IArray"), + ("IArray", Field, "scala.IArray"), + ) } @Test def completionFromJavaDefaults: Unit = { - code"class Foo { val foo: Runn${m1} }".withSource - .completion(m1, Set( + code"class Foo { val foo: Runn${m1} }" + .completion( ("Runnable", Class, "java.lang.Runnable"), - ("Runnable", Module, "Runnable") - )) + ("Runnable", Module, "Runnable"), + ) } @Test def completionWithImplicitConversion: Unit = { @@ -59,7 +64,7 @@ class CompletionTest { code"object Foo { implicit class WithBaz(bar: Bar) { def baz = 0 } }", code"class Bar", code"object Main { import Foo._; val bar: Bar = new Bar; bar.b${m1} }" - ) .completion(m1, Set(("baz", Method, "=> Int"))) + ).completion(("baz", Method, "=> Int")) } // TODO: Also add tests with concrete classes, where the completion will @@ -69,14 +74,14 @@ class CompletionTest { withSources( code"""object Foo { abstract class MyClass }""", code"""import Foo.My${m1}""" - ).completion(m1, Set(("MyClass", Class, "Foo.MyClass"))) + ).completion(("MyClass", Class, "Foo.MyClass")) } @Test def importCompleteClassNoPrefix: Unit = { withSources( code"""object Foo { abstract class MyClass }""", code"""import Foo.${m1}""" - ).completion(m1, completionItems => { + ).completion(completionItems => { val results = CodeCompletion.simplifyResults(completionItems) val myClass = ("MyClass", Class, "Foo.MyClass") assertTrue(results.contains(("MyClass", Class, "Foo.MyClass"))) @@ -95,14 +100,14 @@ class CompletionTest { abstract class MyClass""", code"""package b import a.My${m1}""" - ).completion(m1, Set(("MyClass", Class, "a.MyClass"))) + ).completion(("MyClass", Class, "a.MyClass")) } @Test def importCompleteFromClass: Unit = { withSources( code"""abstract class Foo { val x: Int = 0 }""", code"""import Foo.${m1}""" - ).completion(m1, Set()) + ).noCompletions() } @Test def importCompleteIncludesSynthetic: Unit = { @@ -110,18 +115,18 @@ class CompletionTest { object O { val x = MyCaseClass(0) import x.c${m1} - }""".withSource + }""" .completion( - m1, - Set(("copy", Method, "(foobar: Int): MyCaseClass"), - ("canEqual", Method, "(that: Any): Boolean"))) + ("copy", Method, "(foobar: Int): MyCaseClass"), + ("canEqual", Method, "(that: Any): Boolean"), + ) } @Test def importCompleteIncludeModule: Unit = { withSources( code"""object O { object MyObject }""", code"""import O.My${m1}""" - ).completion(m1, Set(("MyObject", Module, "O.MyObject"))) + ).completion(("MyObject", Module, "O.MyObject")) } @Test def importCompleteWithClassAndCompanion: Unit = { @@ -131,8 +136,10 @@ class CompletionTest { object Foo""", code"""package pgk1 import pkg0.F${m1}""" - ).completion(m1, Set(("Foo", Class, "pkg0.Foo"), - ("Foo", Module, "pkg0.Foo"))) + ).completion( + ("Foo", Class, "pkg0.Foo"), + ("Foo", Module, "pkg0.Foo"), + ) } @Test def importCompleteIncludePackage: Unit = { @@ -140,7 +147,7 @@ class CompletionTest { code"""package foo.bar abstract classFizz""", code"""import foo.b${m1}""" - ).completion(m1, Set(("bar", Module, "foo.bar"))) + ).completion(("bar", Module, "foo.bar")) } @Test def importCompleteIncludeMembers: Unit = { @@ -154,28 +161,32 @@ class CompletionTest { trait myTrait }""", code"""import MyObject.my${m1}""" - ).completion(m1, Set(("myVal", Field, "Int"), - ("myDef", Method, "=> Int"), - ("myVar", Variable, "Int"), - ("myObject", Module, "MyObject.myObject"), - ("myClass", Class, "MyObject.myClass"), - ("myTrait", Class, "MyObject.myTrait"))) + ).completion( + ("myVal", Field, "Int"), + ("myDef", Method, "=> Int"), + ("myVar", Variable, "Int"), + ("myObject", Module, "MyObject.myObject"), + ("myClass", Class, "MyObject.myClass"), + ("myTrait", Class, "MyObject.myTrait"), + ) } @Test def importJavaClass: Unit = { - code"""import java.io.FileDesc${m1}""".withSource - .completion(m1, Set(("FileDescriptor", Class, "java.io.FileDescriptor"), - ("FileDescriptor", Module, "java.io.FileDescriptor"))) + code"""import java.io.FileDesc${m1}""" + .completion( + ("FileDescriptor", Class, "java.io.FileDescriptor"), + ("FileDescriptor", Module, "java.io.FileDescriptor"), + ) } @Test def importJavaStaticMethod: Unit = { - code"""import java.lang.System.lineSep${m1}""".withSource - .completion(m1, Set(("lineSeparator", Method, "(): String"))) + code"""import java.lang.System.lineSep${m1}""" + .completion(("lineSeparator", Method, "(): String")) } @Test def importJavaStaticField: Unit = { - code"""import java.lang.System.ou${m1}""".withSource - .completion(m1, Set(("out", Field, "java.io.PrintStream"))) + code"""import java.lang.System.ou${m1}""" + .completion(("out", Field, "java.io.PrintStream")) } @Test def importFromExplicitAndSyntheticPackageObject: Unit = { @@ -183,27 +194,33 @@ class CompletionTest { code"package foo.bar; trait XXXX1", code"package foo; package object bar { trait XXXX2 }", code"object Main { import foo.bar.XX${m1} }" - ) .completion(m1, Set(("XXXX1", Class, "foo.bar.XXXX1"), ("XXXX2", Class, "foo.bar.XXXX2"))) + ).completion( + ("XXXX1", Class, "foo.bar.XXXX1"), + ("XXXX2", Class, "foo.bar.XXXX2"), + ) } @Test def completeJavaModuleClass: Unit = { code"""object O { val out = java.io.FileDesc${m1} - }""".withSource - .completion(m1, Set(("FileDescriptor", Module, "java.io.FileDescriptor"))) + }""" + .completion(("FileDescriptor", Module, "java.io.FileDescriptor")) } @Test def importRename: Unit = { - code"""import java.io.{FileDesc${m1} => Foo}""".withSource - .completion(m1, Set(("FileDescriptor", Class, "java.io.FileDescriptor"), - ("FileDescriptor", Module, "java.io.FileDescriptor"))) + code"""import java.io.{FileDesc${m1} => Foo}""" + .completion( + ("FileDescriptor", Class, "java.io.FileDescriptor"), + ("FileDescriptor", Module, "java.io.FileDescriptor"), + ) + } @Test def importGivenByType: Unit = { code"""trait Foo object Bar - import Bar.{given Fo$m1}""".withSource - .completion(m1, Set(("Foo", Class, "Foo"))) + import Bar.{given Fo$m1}""" + .completion(("Foo", Class, "Foo")) } @Test def markDeprecatedSymbols: Unit = { @@ -211,8 +228,8 @@ class CompletionTest { @deprecated val bar = 0 } - import Foo.ba${m1}""".withSource - .completion(m1, results => { + import Foo.ba${m1}""" + .completion(results => { assertEquals(1, results.size) val result = results.head assertEquals("bar", result.getLabel) @@ -223,8 +240,8 @@ class CompletionTest { @Test def i4397: Unit = { code"""class Foo { | .${m1} - |}""".withSource - .completion(m1, Set()) + |}""" + .noCompletions() } @Test def completeNoPrefix: Unit = { @@ -232,8 +249,8 @@ class CompletionTest { |object Bar { | val foo = new Foo | foo.${m1} - |}""".withSource - .completion(m1, results => assertTrue(results.nonEmpty)) + |}""" + .completion(results => assertTrue(results.nonEmpty)) } @Test def completeErrorKnowsKind: Unit = { @@ -241,8 +258,8 @@ class CompletionTest { | abstract class Zig | val Zag: Int = 0 | val b = 3 + Bar.${m1} - |}""".withSource - .completion(m1, completionItems => { + |}""" + .completion(completionItems => { val results = CodeCompletion.simplifyResults(completionItems) assertTrue(results.contains(("Zag", Field, "Int"))) assertFalse(results.exists((label, _, _) => label == "Zig")) @@ -256,37 +273,46 @@ class CompletionTest { | def baz = new Bar | object bat | val bizz: ba${m1} - |}""".withSource - .completion(m1, Set(("bar", Field, "Bar"), ("bat", Module, "Foo.bat"))) + |}""" + .completion( + ("bar", Field, "Bar"), + ("bat", Module, "Foo.bat"), + ) } @Test def completionOnRenamedImport: Unit = { code"""import java.io.{FileDescriptor => AwesomeStuff} - trait Foo { val x: Awesom$m1 }""".withSource - .completion(m1, Set(("AwesomeStuff", Class, "java.io.FileDescriptor"), - ("AwesomeStuff", Module, "java.io.FileDescriptor"))) + trait Foo { val x: Awesom${m1}}""" + .completion( + ("AwesomeStuff", Class, "java.io.FileDescriptor"), + ("AwesomeStuff", Module, "java.io.FileDescriptor"), + ) } @Test def completionOnRenamedImport2: Unit = { code"""import java.util.{HashMap => MyImportedSymbol} trait Foo { import java.io.{FileDescriptor => MyImportedSymbol} - val x: MyImp$m1 - }""".withSource - .completion(m1, Set(("MyImportedSymbol", Class, "java.io.FileDescriptor"), - ("MyImportedSymbol", Module, "java.io.FileDescriptor"))) + val x: MyImp${m1} + }""" + .completion( + ("MyImportedSymbol", Class, "java.io.FileDescriptor"), + ("MyImportedSymbol", Module, "java.io.FileDescriptor"), + ) } @Test def completionRenamedAndOriginalNames: Unit = { code"""import java.util.HashMap |trait Foo { | import java.util.{HashMap => HashMap2} - | val x: Hash$m1 - |}""".withSource - .completion(m1, Set(("HashMap", Class, "java.util.HashMap"), - ("HashMap", Module, "java.util.HashMap"), - ("HashMap2", Class, "java.util.HashMap"), - ("HashMap2", Module, "java.util.HashMap"))) + | val x: Hash${m1} + |}""" + .completion( + ("HashMap", Class, "java.util.HashMap"), + ("HashMap", Module, "java.util.HashMap"), + ("HashMap2", Class, "java.util.HashMap"), + ("HashMap2", Module, "java.util.HashMap"), + ) } @Test def completionRenamedThrice: Unit = { @@ -294,14 +320,16 @@ class CompletionTest { |import java.util.{HashMap => MyHashMap2} |trait Foo { | import java.util.{HashMap => MyHashMap3} - | val x: MyHash$m1 - |}""".withSource - .completion(m1, Set(("MyHashMap", Class, "java.util.HashMap"), - ("MyHashMap", Module, "java.util.HashMap"), - ("MyHashMap2", Class, "java.util.HashMap"), - ("MyHashMap2", Module, "java.util.HashMap"), - ("MyHashMap3", Class, "java.util.HashMap"), - ("MyHashMap3", Module, "java.util.HashMap"))) + | val x: MyHash${m1} + |}""" + .completion( + ("MyHashMap", Class, "java.util.HashMap"), + ("MyHashMap", Module, "java.util.HashMap"), + ("MyHashMap2", Class, "java.util.HashMap"), + ("MyHashMap2", Module, "java.util.HashMap"), + ("MyHashMap3", Class, "java.util.HashMap"), + ("MyHashMap3", Module, "java.util.HashMap"), + ) } @Test def completeFromWildcardImports: Unit = { @@ -311,26 +339,21 @@ class CompletionTest { | given fooInt: Int = 0 | given fooString: String = "" |} - |object Test1 { import Foo.{fooFloat => _, _}; foo$m1 } - |object Test2 { import Foo.given; foo$m2 } - |object Test3 { import Foo.{given String}; foo$m3 } - |object Test4 { import Foo.{_, given String}; foo$m4 } - |object Test5 { import Foo.{fooFloat, given}; foo$m5 } - |object Test6 { import Foo.{fooInt => _, fooString => fooStr, given}; foo$m6 } - |object Test7 { import Foo.{fooLong => fooInt, given Int}; foo$m7 } - """.withSource - .completion(m1, Set(("fooLong", Field, "Long"))) - .completion(m2, Set(("fooInt", Field, "Int"), - ("fooString", Field, "String"))) - .completion(m3, Set(("fooString", Field, "String"))) - .completion(m4, Set(("fooLong", Field, "Long"), - ("fooFloat", Field, "Float"), - ("fooString", Field, "String"))) - .completion(m5, Set(("fooFloat", Field, "Float"), - ("fooInt", Field, "Int"), - ("fooString", Field, "String"))) - .completion(m6, Set(("fooStr", Field, "String"))) - .completion(m7, Set(("fooInt", Field, "Long"))) + |object Test1 { import Foo.{fooFloat => _, _}; foo${m1} } + |object Test2 { import Foo.given; foo${m2} } + |object Test3 { import Foo.{given String}; foo${m3} } + |object Test4 { import Foo.{_, given String}; foo${m4} } + |object Test5 { import Foo.{fooFloat, given}; foo${m5} } + |object Test6 { import Foo.{fooInt => _, fooString => fooStr, given}; foo${m6} } + |object Test7 { import Foo.{fooLong => fooInt, given Int}; foo${m7} } + """ + .completion(m1, ("fooLong", Field, "Long")) + .completion(m2, ("fooInt", Field, "Int"), ("fooString", Field, "String")) + .completion(m3, ("fooString", Field, "String")) + .completion(m4, ("fooLong", Field, "Long"), ("fooFloat", Field, "Float"), ("fooString", Field, "String")) + .completion(m5, ("fooFloat", Field, "Float"), ("fooInt", Field, "Int"), ("fooString", Field, "String")) + .completion(m6, ("fooStr", Field, "String")) + .completion(m7, ("fooInt", Field, "Long")) } @Test def dontCompleteFromAmbiguousImportsFromSameSite: Unit = { @@ -340,9 +363,9 @@ class CompletionTest { |} |object Test { | import Foo.{i => xxxx, j => xxxx} - | val x = xx$m1 - |}""".withSource - .completion(m1, Set()) + | val x = xx${m1} + |}""" + .noCompletions() } @Test def collectNamesImportedInNestedScopes: Unit = { @@ -361,18 +384,22 @@ class CompletionTest { | import Bar.xxxx2 | locally { | import Baz.xxxx3 - | val x = xx$m1 + | val x = xx${m1} | } | } - |}""".withSource - .completion(m1, Set(("xxxx1", Field, "Int"), ("xxxx2", Field, "Int"), ("xxxx3", Field, "Int"))) + |}""" + .completion( + ("xxxx1", Field, "Int"), + ("xxxx2", Field, "Int"), + ("xxxx3", Field, "Int"), + ) } @Test def completeEnclosingObject: Unit = { code"""object Test { - | def x = Tes$m1 - |}""".withSource - .completion(m1, Set(("Test", Module, "Test"))) + | def x = Tes${m1} + |}""" + .completion(("Test", Module, "Test")) } @Test def completeBothDefinitionsForEqualNestingLevels: Unit = { @@ -383,10 +410,12 @@ class CompletionTest { | def xxxx(s: String): String = s |} |object Test extends Foo, Bar { - | val x = xx$m1 - |}""".withSource - .completion(m1, Set(("xxxx", Method, "(s: String): String"), - ("xxxx", Method, "(i: Int): Int"))) + | val x = xx${m1} + |}""" + .completion( + ("xxxx", Method, "(s: String): String"), + ("xxxx", Method, "(i: Int): Int"), + ) } @Test def dontCompleteFromAmbiguousImportsForEqualNestingLevels: Unit = { @@ -399,9 +428,9 @@ class CompletionTest { |object Test { | import Foo.xxxx | import Bar.xxxx - | val x = xx$m1 - |}""".withSource - .completion(m1, Set()) + | val x = xx${m1} + |}""" + .noCompletions() } @Test def completeFromSameImportsForEqualNestingLevels: Unit = { @@ -412,9 +441,9 @@ class CompletionTest { | import Foo.xxxx | import Foo.xxxx | import Foo.xxxx - | val x = xx$m1 - |}""".withSource - .completion(m1, Set(("xxxx", Method, "(i: Int): Int"))) + | val x = xx${m1} + |}""" + .completion(("xxxx", Method, "(i: Int): Int")) } @Test def preferLocalDefinitionToImportForEqualNestingLevels: Unit = { @@ -424,9 +453,9 @@ class CompletionTest { |object Test { | def xxxx(s: String): String = s | import Foo.xxxx - | val x = xx$m1 - |}""".withSource - .completion(m1, Set(("xxxx", Method, "(s: String): String"))) + | val x = xx${m1} + |}""" + .completion(("xxxx", Method, "(s: String): String")) } @Test def preferMoreDeeplyNestedDefinition: Unit = { @@ -434,10 +463,10 @@ class CompletionTest { | def xxxx(i: Int): Int = i | object Inner { | def xxxx(s: String): String = s - | val x = xx$m1 + | val x = xx${m1} | } - |}""".withSource - .completion(m1, Set(("xxxx", Method, "(s: String): String"))) + |}""" + .completion(("xxxx", Method, "(s: String): String")) } @Test def preferMoreDeeplyNestedImport: Unit = { @@ -451,10 +480,10 @@ class CompletionTest { | import Foo.xxxx | locally { | import Bar.xxxx - | val x: String = xx$m1 + | val x: String = xx${m1} | } - |}""".withSource - .completion(m1, Set(("xxxx", Method, "(s: String): String"))) + |}""" + .completion(("xxxx", Method, "(s: String): String")) } @Test def preferMoreDeeplyNestedLocalDefinitionToImport: Unit = { @@ -465,10 +494,10 @@ class CompletionTest { | import Foo.xxxx | object Inner { | def xxxx(s: String): String = s - | val x: String = xx$m1 + | val x: String = xx${m1} | } - |}""".withSource - .completion(m1, Set(("xxxx", Method, "(s: String): String"))) + |}""" + .completion(("xxxx", Method, "(s: String): String")) } @Test def dontCompleteLocalDefinitionShadowedByImport: Unit = { @@ -480,11 +509,11 @@ class CompletionTest { | val xxxx = "" | locally { | import XXXX.xxxx // import conflicts with val from outer scope - | val y = xx$m1 + | val y = xx${m1} | } | } - |}""".withSource - .completion(m1, Set()) + |}""" + .noCompletions() } @Test def completeFromLocalDefinitionIgnoringLessDeeplyNestedAmbiguities: Unit = { @@ -498,12 +527,12 @@ class CompletionTest { | import XXXX.xxxx // import conflicts with val from outer scope | locally { | val xxxx = 'a' // shadows both the import and the val from outer scope - | val y = xx$m1 + | val y = xx${m1} | } | } | } - |}""".withSource - .completion(m1, Set(("xxxx", Field, "Char"))) + |}""" + .completion(("xxxx", Field, "Char")) } @Test def completionClassAndMethod: Unit = { @@ -511,9 +540,11 @@ class CompletionTest { | class bar | def bar(i: Int) = 0 |} - |import Foo.b$m1""".withSource - .completion(m1, Set(("bar", Class, "Foo.bar"), - ("bar", Method, "(i: Int): Int"))) + |import Foo.b${m1}""" + .completion( + ("bar", Class, "Foo.bar"), + ("bar", Method, "(i: Int): Int"), + ) } @Test def completionTypeAndLazyValue: Unit = { @@ -521,9 +552,11 @@ class CompletionTest { | type bar = Int | lazy val bar = 3 |} - |import Foo.b$m1""".withSource - .completion(m1, Set(("bar", Field, "Foo.bar"), - ("bar", Field, "Int"))) + |import Foo.b${m1}""" + .completion( + ("bar", Field, "Foo.bar"), + ("bar", Field, "Int"), + ) } @Test def keepTrackOfTermsAndTypesSeparately: Unit = { @@ -534,12 +567,11 @@ class CompletionTest { |object Test { | import XXXX._ | val YYYY = Int - | val ZZZZ = YY$m1 - | type ZZZZ = YY$m2 - |}""".withSource - .completion(m1, Set(("YYYY", Field, "Int"))) - .completion(m2, Set(("YYYY", Field, "XXXX.YYYY"), - ("YYYY", Field, "Int"))) + | val ZZZZ = YY${m1} + | type ZZZZ = YY${m2} + |}""" + .completion(m1, ("YYYY", Field, "Int")) + .completion(m2, ("YYYY", Field, "XXXX.YYYY"), ("YYYY", Field, "Int")) } @Test def completeRespectingAccessModifiers: Unit = { @@ -549,14 +581,14 @@ class CompletionTest { | private def xxxx3 = "" |} |object Test1 extends Foo { - | xx$m1 + | xx${m1} |} |object Test2 { | val foo = new Foo {} - | foo.xx$m2 - |}""".withSource - .completion(m1, Set(("xxxx1", Method, "=> String"), ("xxxx2", Method, "=> String"))) - .completion(m2, Set(("xxxx1", Method, "=> String"))) + | foo.xx${m2} + |}""" + .completion(m1, ("xxxx1", Method, "=> String"), ("xxxx2", Method, "=> String")) + .completion(m2, ("xxxx1", Method, "=> String")) } @Test def completeFromPackageObjectWithInheritance: Unit = { @@ -564,74 +596,75 @@ class CompletionTest { |trait Foo[A] { def xxxx(a: A) = a } |package object foo extends Foo[Int] {} |object Test { - | foo.xx$m1 - |}""".withSource - .completion(m1, Set(("xxxx", Method, "(a: Int): Int"))) + | foo.xx${m1} + |}""" + .completion(("xxxx", Method, "(a: Int): Int")) } @Test def completePrimaryConstructorParameter: Unit = { + val expected = Set(("abc", Field, "Int")) + code"""class Foo(abc: Int) { - | ab$m1 + | ab${m1} | def method1: Int = { - | ab$m2 + | ab${m2} | 42 | } | def method2: Int = { - | val smth = ab$m3 + | val smth = ab${m3} | 42 | } - |}""".withSource - .completion(m1, Set(("abc", Field, "Int"))) - .completion(m2, Set(("abc", Field, "Int"))) - .completion(m2, Set(("abc", Field, "Int"))) + |}""" + .completion(m1, expected) + .completion(m2, expected) + .completion(m3, expected) } @Test def completeExtensionReceiver: Unit = { - code"""extension (string: String) def xxxx = str$m1""" - .withSource - .completion(m1, Set(("string", Field, "String"))) + code"""extension (string: String) def xxxx = str${m1}""" + .completion(("string", Field, "String")) } @Test def completeExtensionMethodWithoutParameter: Unit = { code"""object Foo |extension (foo: Foo.type) def xxxx = 1 - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> Int"))) + |object Main { Foo.xx${m1} }""" + .completion(("xxxx", Method, "=> Int")) } @Test def completeExtensionMethodWithParameter: Unit = { code"""object Foo |extension (foo: Foo.type) def xxxx(i: Int) = i - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "(i: Int): Int"))) + |object Main { Foo.xx${m1} }""" + .completion(("xxxx", Method, "(i: Int): Int")) } @Test def completeExtensionMethodWithTypeParameter: Unit = { code"""object Foo |extension (foo: Foo.type) def xxxx[A]: Int = 1 - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "[A] => Int"))) + |object Main { Foo.xx${m1} }""" + .completion(("xxxx", Method, "[A] => Int")) } @Test def completeExtensionMethodWithParameterAndTypeParameter: Unit = { code"""object Foo |extension (foo: Foo.type) def xxxx[A](a: A) = a - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "[A](a: A): A"))) + |object Main { Foo.xx${m1} }""" + .completion(("xxxx", Method, "[A](a: A): A")) } @Test def completeExtensionMethodFromExtensionWithTypeParameter: Unit = { code"""extension [A](a: A) def xxxx: A = a - |object Main { "abc".xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> String"))) + |object Main { "abc".xx${m1} }""" + .completion(("xxxx", Method, "=> String")) } @Test def completeExtensionMethodWithResultTypeDependantOnReceiver: Unit = { code"""trait Foo { type Out; def get: Out} |object Bar extends Foo { type Out = String; def get: Out = "abc"} |extension (foo: Foo) def xxxx: foo.Out = foo.get - |object Main { Bar.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> String"))) + |object Main { Bar.xx${m1} }""" + .completion(("xxxx", Method, "=> String")) } @Test def completeExtensionMethodFromExtenionWithPrefixUsingSection: Unit = { @@ -641,8 +674,8 @@ class CompletionTest { |given Bar with {} |given Baz with {} |extension (using Bar, Baz)(foo: Foo.type) def xxxx = 1 - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> Int"))) + |object Main { Foo.xx${m1} }""" + .completion(("xxxx", Method, "=> Int")) } @Test def completeExtensionMethodFromExtenionWithMultiplePrefixUsingSections: Unit = { @@ -652,8 +685,8 @@ class CompletionTest { |given Bar with {} |given Baz with {} |extension (using Bar)(using Baz)(foo: Foo.type) def xxxx = 1 - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> Int"))) + |object Main { Foo.xx${m1} }""" + .completion(("xxxx", Method, "=> Int")) } @Test def dontCompleteExtensionMethodFromExtenionWithMissingImplicitFromPrefixUsingSection: Unit = { @@ -662,8 +695,8 @@ class CompletionTest { |trait Baz |given Baz with {} |extension (using Bar, Baz)(foo: Foo.type) def xxxx = 1 - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set()) + |object Main { Foo.xx${m1} }""" + .noCompletions() } @Test def completeExtensionMethodForReceiverOfTypeDependentOnLeadingImplicits: Unit = { @@ -687,8 +720,8 @@ class CompletionTest { |object Quux: | extension (using foo: Foo)(using fooOut: foo.Out)(fooOutOut: fooOut.Out) def xxxx = "abc" | - |object Main { (new Quux).xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> String"))) + |object Main { (new Quux).xx${m1} }""" + .completion(("xxxx", Method, "=> String")) } @Test def completeExtensionMethodWithResultTypeDependentOnLeadingImplicit: Unit = { @@ -696,8 +729,8 @@ class CompletionTest { |trait Bar { type Out; def get: Out } |given Bar with { type Out = 123; def get: Out = 123 } |extension (using bar: Bar)(foo: Foo.type) def xxxx: bar.Out = bar.get - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> (123 : Int)"))) + |object Main { Foo.xx${m1} }""" + .completion(("xxxx", Method, "=> (123 : Int)")) } @Test def completeExtensionMethodFromExtenionWithPostfixUsingSection: Unit = { @@ -707,8 +740,8 @@ class CompletionTest { |given Bar with {} |given Baz with {} |extension (foo: Foo.type)(using Bar, Baz) def xxxx = 1 - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "(using x$2: Bar, x$3: Baz): Int"))) + |object Main { Foo.xx${m1} }""" + .completion(("xxxx", Method, "(using x$2: Bar, x$3: Baz): Int")) } @Test def completeExtensionMethodFromExtenionWithMultiplePostfixUsingSections: Unit = { @@ -718,8 +751,8 @@ class CompletionTest { |given Bar with {} |given Baz with {} |extension (foo: Foo.type)(using Bar)(using Baz) def xxxx = 1 - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "(using x$2: Bar)(using x$3: Baz): Int"))) + |object Main { Foo.xx${m1} }""" + .completion(("xxxx", Method, "(using x$2: Bar)(using x$3: Baz): Int")) } @Test def completeExtensionMethodWithTypeParameterFromExtenionWithTypeParametersAndPrefixAndPostfixUsingSections: Unit = { @@ -728,8 +761,8 @@ class CompletionTest { |given Bar with {} |given Baz with {} |extension [A](using bar: Bar)(a: A)(using baz: Baz) def xxxx[B]: Either[A, B] = Left(a) - |object Main { 123.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "(using baz: Baz): [B] => Either[Int, B]"))) + |object Main { 123.xx${m1} }""" + .completion(("xxxx", Method, "(using baz: Baz): [B] => Either[Int, B]")) } @Test def completeExtensionMethodWithTypeBounds: Unit = { @@ -738,8 +771,8 @@ class CompletionTest { |given Bar with {} |extension [A >: Bar](a: A) def xxxx[B <: a.type]: Either[A, B] = Left(a) |val foo = new Foo {} - |object Main { foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "[B <: (foo : Foo)] => Either[Foo, B]"))) + |object Main { foo.xx${m1} }""" + .completion(("xxxx", Method, "[B <: (foo : Foo)] => Either[Foo, B]")) } @Test def completeInheritedExtensionMethod: Unit = { @@ -747,8 +780,8 @@ class CompletionTest { |trait FooOps { | extension (foo: Foo.type) def xxxx = 1 |} - |object Main extends FooOps { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> Int"))) + |object Main extends FooOps { Foo.xx${m1} }""" + .completion(("xxxx", Method, "=> Int")) } @Test def completeExtensionMethodWithoutLosingTypeParametersFromGivenInstance: Unit = { @@ -756,8 +789,8 @@ class CompletionTest { | extension (xs: List[A]) def xxxx = xs |} |given ListOps[Int] with {} - |object Main { List(1, 2, 3).xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> List[Int]"))) + |object Main { List(1, 2, 3).xx${m1} }""" + .completion(("xxxx", Method, "=> List[Int]")) } @Test def completeRenamedExtensionMethod: Unit = { @@ -766,8 +799,8 @@ class CompletionTest { | extension (foo: Foo.type) def xxxx = 1 |} |import FooOps.{xxxx => yyyy} - |object Main { Foo.yy${m1} }""".withSource - .completion(m1, Set(("yyyy", Method, "=> Int"))) + |object Main { Foo.yy${m1} }""" + .completion(("yyyy", Method, "=> Int")) } @Test def completeExtensionMethodFromGivenInstanceDefinedInScope: Unit = { @@ -776,8 +809,8 @@ class CompletionTest { |given FooOps with { | extension (foo: Foo.type) def xxxx = 1 |} - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> Int"))) + |object Main { Foo.xx${m1} }""" + .completion(("xxxx", Method, "=> Int")) } @Test def completeExtensionMethodFromImportedGivenInstance: Unit = { @@ -789,8 +822,8 @@ class CompletionTest { | } |} |import Bar.given - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> Int"))) + |object Main { Foo.xx${m1} }""" + .completion(("xxxx", Method, "=> Int")) } @Test def completeExtensionMethodFromImplicitScope: Unit = { @@ -798,8 +831,8 @@ class CompletionTest { |object Foo { | extension (foo: Foo) def xxxx = foo.i |} - |object Main { Foo(123).xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> Int"))) + |object Main { Foo(123).xx${m1} }""" + .completion(("xxxx", Method, "=> Int")) } @Test def completeExtensionMethodFromGivenInImplicitScope: Unit = { @@ -810,8 +843,8 @@ class CompletionTest { | extension (foo: Foo) def xxxx = foo.i | } |} - |object Main { Foo(123).xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> Int"))) + |object Main { Foo(123).xx${m1} }""" + .completion(("xxxx", Method, "=> Int")) } @Test def completeExtensionMethodOnResultOfImplicitConversion: Unit = { @@ -819,15 +852,15 @@ class CompletionTest { |case class Foo(i: Int) |extension (foo: Foo) def xxxx = foo.i |given Conversion[Int, Foo] = Foo(_) - |object Main { 123.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> Int"))) + |object Main { 123.xx${m1} }""" + .completion(("xxxx", Method, "=> Int")) } @Test def dontCompleteExtensionMethodWithMismatchedName: Unit = { code"""object Foo |extension (foo: Foo.type) def xxxx = 1 - |object Main { Foo.yy${m1} }""".withSource - .completion(m1, Set()) + |object Main { Foo.yy${m1} }""" + .noCompletions() } @Test def preferNormalMethodToExtensionMethod: Unit = { @@ -837,8 +870,8 @@ class CompletionTest { |object FooOps { | extension (foo: Foo.type) def xxxx = 1 |} - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> String"))) + |object Main { Foo.xx${m1} }""" + .completion(("xxxx", Method, "=> String")) } @Test def preferExtensionMethodFromExplicitScope: Unit = { @@ -847,340 +880,274 @@ class CompletionTest { |object FooOps { | extension (foo: Foo.type) def xxxx = "abcd" |} - |object Main { Foo.xx${m1} }""".withSource - .completion(m1, Set(("xxxx", Method, "=> Int"))) + |object Main { Foo.xx${m1} }""" + .completion(("xxxx", Method, "=> Int")) } @Test def dontCompleteExtensionMethodWithMismatchedReceiverType: Unit = { code"""extension (i: Int) def xxxx = i - |object Main { "abc".xx${m1} }""".withSource - .completion(m1, Set()) + |object Main { "abc".xx${m1} }""" + .noCompletions() } @Test def i13365: Unit = { - code"""|import scala.quoted._ - | - |object Test { - | def test(using Quotes)(str: String) = { - | import quotes.reflect._ - | val msg = Expr(str) - | val printHello = '{ print("sdsd") } - | val tree = printHello.asTerm - | tree.sh${m1} - | } - |}""".withSource - .completion(m1, Set(("show",Method, "(using x$2: x$1.reflect.Printer[x$1.reflect.Tree]): String"))) + code"""import scala.quoted._ + | + |object Test { + | def test(using Quotes)(str: String) = { + | import quotes.reflect._ + | val msg = Expr(str) + | val printHello = '{ print("sdsd") } + | val tree = printHello.asTerm + | tree.sh${m1} + | } + |}""" + .completion(("show",Method, "(using x$2: x$1.reflect.Printer[x$1.reflect.Tree]): String")) } @Test def syntheticThis: Unit = { - code"""|class Y() { - | def bar: Unit = - | val argument: Int = ??? - | arg${m1} - | - | def arg: String = ??? - |} - |""".withSource - .completion(m1, Set(("arg", Method, "=> String"), - ("argument", Field, "Int"))) + code"""class Y() { + | def bar: Unit = + | val argument: Int = ??? + | arg${m1} + | + | def arg: String = ??? + |} + |""" + .completion( + ("arg", Method, "=> String"), + ("argument", Field, "Int") + ) } @Test def concatMethodWithImplicits: Unit = { - code"""|object A { - | Array.concat${m1} - |}""".withSource - .completion( - m1, - Set( - ( - "concat", - Method, - "[T](xss: Array[T]*)(implicit evidence$11: scala.reflect.ClassTag[T]): Array[T]" - ) - ) - ) + code"""object A { + | Array.concat${m1} + |}""" + .completion(("concat", Method, "[T](xss: Array[T]*)(implicit evidence$11: scala.reflect.ClassTag[T]): Array[T]")) } @Test def i12465_hkt: Unit = - code"""???.asInstanceOf[scala.collection.Seq].${m1}""".withSource - .completion(m1, Set()) + code"""???.asInstanceOf[scala.collection.Seq].${m1}""" + .noCompletions() @Test def i12465_hkt_alias: Unit = - code"""???.asInstanceOf[Seq].${m1}""".withSource - .completion(m1, Set()) + code"""???.asInstanceOf[Seq].${m1}""" + .noCompletions() @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") - ) + val expected1 = Set( + ("MyAnnotation", Class, "MyAnnotation"), + ("MyAnnotation", Module, "MyAnnotation"), ) + val expected2 = Set( + ("MyAnnotation", Class, "Foo.MyAnnotation"), + ("MyAnnotation", Module, "Foo.MyAnnotation"), + ) + 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}) + |""" + .completion(m1, expected1) + .completion(m2, expected1) + .completion(m3, expected2) + .completion(m4, expected1) + .completion(m5, expected2) + .completion(m6, expected2) @Test def i13624_annotation : Unit = code"""@annotation.implicitNot${m1} |@annotation.implicitNotFound @mai${m2}""" - .withSource - .completion(m1, - Set( - ("implicitNotFound", Class, "scala.annotation.implicitNotFound"), - ("implicitNotFound", Module, "scala.annotation.implicitNotFound") - ) - ) - .completion(m2, - Set( - ("main", Class, "scala.main"), - ("main", Module, "main") - ) - ) + .completion(m1, + ("implicitNotFound", Class, "scala.annotation.implicitNotFound"), + ("implicitNotFound", Module, "scala.annotation.implicitNotFound"), + ) + .completion(m2, + ("main", Class, "scala.main"), + ("main", Module, "main"), + ) @Test def i13623_annotation : Unit = code"""import annot${m1}""" - .withSource - .completion(m1, - Set( - ("annotation", Module, "scala.annotation") - ) - ) + .completion(("annotation", Module, "scala.annotation")) @Test def importAnnotationAfterImport : Unit = code"""import java.lang.annotation; import annot${m1}""" - .withSource - .completion(m1, - Set( - ("annotation", Module, "scala.annotation") - ) - ) + .completion(("annotation", Module, "scala.annotation")) + @Test def completeTemplateConstrArgType: Unit = { - val expected = Set( - ("Future", Class, "scala.concurrent.Future"), - ("Future", Module, "scala.concurrent.Future") - ) code"""import scala.concurrent.Future - |class Foo(x: Fut${m1})""".withSource - .completion(m1, expected) + |class Foo(x: Fut${m1})""" + .completion( + ("Future", Class, "scala.concurrent.Future"), + ("Future", Module, "scala.concurrent.Future") + ) } @Test def completeTemplateParents: Unit = { - val expected = Set( - ("Future", Class, "scala.concurrent.Future"), - ("Future", Module, "scala.concurrent.Future") - ) code"""import scala.concurrent.Future - |class Foo extends Futu${m1}""".withSource - .completion(m1, expected) + |class Foo extends Futu${m1}""" + .completion( + ("Future", Class, "scala.concurrent.Future"), + ("Future", Module, "scala.concurrent.Future") + ) } @Test def completeTemplateSelfType: Unit = { - val expected = Set( - ("Future", Class, "scala.concurrent.Future"), - ("Future", Module, "scala.concurrent.Future") - ) code"""import scala.concurrent.Future - |class Foo[A]{ self: Futu${m1} => }""".withSource - .completion(m1, expected) + |class Foo[A]{ self: Futu${m1} => }""" + .completion( + ("Future", Class, "scala.concurrent.Future"), + ("Future", Module, "scala.concurrent.Future") + ) } @Test def backticks: Unit = { - val expected = Set( - ("getClass", Method, "[X0 >: Foo.Bar.type](): Class[? <: X0]"), - ("ensuring", Method, "(cond: Boolean): A"), - ("##", Method, "=> Int"), - ("nn", Method, "=> Foo.Bar.type"), - ("==", Method, "(x$0: Any): Boolean"), - ("ensuring", Method, "(cond: Boolean, msg: => Any): A"), - ("ne", Method, "(x$0: Object): Boolean"), - ("valueOf", Method, "($name: String): Foo.Bar"), - ("equals", Method, "(x$0: Any): Boolean"), - ("wait", Method, "(x$0: Long): Unit"), - ("hashCode", Method, "(): Int"), - ("notifyAll", Method, "(): Unit"), - ("values", Method, "=> Array[Foo.Bar]"), - ("→", Method, "[B](y: B): (A, B)"), - ("!=", Method, "(x$0: Any): Boolean"), - ("fromOrdinal", Method, "(ordinal: Int): Foo.Bar"), - ("asInstanceOf", Method, "[X0] => X0"), - ("->", Method, "[B](y: B): (A, B)"), - ("wait", Method, "(x$0: Long, x$1: Int): Unit"), - ("`back-tick`", Field, "Foo.Bar"), - ("notify", Method, "(): Unit"), - ("formatted", Method, "(fmtstr: String): String"), - ("ensuring", Method, "(cond: A => Boolean, msg: => Any): A"), - ("wait", Method, "(): Unit"), - ("isInstanceOf", Method, "[X0] => Boolean"), - ("`match`", Field, "Foo.Bar"), - ("toString", Method, "(): String"), - ("ensuring", Method, "(cond: A => Boolean): A"), - ("eq", Method, "(x$0: Object): Boolean"), - ("synchronized", Method, "[X0](x$0: X0): X0") - ) code"""object Foo: - | enum Bar: - | case `back-tick` - | case `match` - | - | val x = Bar.${m1}""" - .withSource.completion(m1, expected) + | enum Bar: + | case `back-tick` + | case `match` + | + | val x = Bar.${m1}""" + .completion( + ("getClass", Method, "[X0 >: Foo.Bar.type](): Class[? <: X0]"), + ("ensuring", Method, "(cond: Boolean): A"), + ("##", Method, "=> Int"), + ("nn", Method, "=> Foo.Bar.type"), + ("==", Method, "(x$0: Any): Boolean"), + ("ensuring", Method, "(cond: Boolean, msg: => Any): A"), + ("ne", Method, "(x$0: Object): Boolean"), + ("valueOf", Method, "($name: String): Foo.Bar"), + ("equals", Method, "(x$0: Any): Boolean"), + ("wait", Method, "(x$0: Long): Unit"), + ("hashCode", Method, "(): Int"), + ("notifyAll", Method, "(): Unit"), + ("values", Method, "=> Array[Foo.Bar]"), + ("→", Method, "[B](y: B): (A, B)"), + ("!=", Method, "(x$0: Any): Boolean"), + ("fromOrdinal", Method, "(ordinal: Int): Foo.Bar"), + ("asInstanceOf", Method, "[X0] => X0"), + ("->", Method, "[B](y: B): (A, B)"), + ("wait", Method, "(x$0: Long, x$1: Int): Unit"), + ("`back-tick`", Field, "Foo.Bar"), + ("notify", Method, "(): Unit"), + ("formatted", Method, "(fmtstr: String): String"), + ("ensuring", Method, "(cond: A => Boolean, msg: => Any): A"), + ("wait", Method, "(): Unit"), + ("isInstanceOf", Method, "[X0] => Boolean"), + ("`match`", Field, "Foo.Bar"), + ("toString", Method, "(): String"), + ("ensuring", Method, "(cond: A => Boolean): A"), + ("eq", Method, "(x$0: Object): Boolean"), + ("synchronized", Method, "[X0](x$0: X0): X0") + ) } @Test def backticksPrefix: Unit = { - val expected = Set( - ("`back-tick`", Field, "Foo.Bar"), - ) code"""object Foo: - | enum Bar: - | case `back-tick` - | case `match` - | - | val x = Bar.`back${m1}""" - .withSource.completion(m1, expected) + | enum Bar: + | case `back-tick` + | case `match` + | + | val x = Bar.`back${m1}""" + .completion(("`back-tick`", Field, "Foo.Bar")) } @Test def backticksSpace: Unit = { - val expected = Set( - ("`has space`", Field, "Foo.Bar"), - ) code"""object Foo: - | enum Bar: - | case `has space` - | - | val x = Bar.`has s${m1}""" - .withSource.completion(m1, expected) + | enum Bar: + | case `has space` + | + | val x = Bar.`has s${m1}""" + .completion(("`has space`", Field, "Foo.Bar")) } @Test def backticksCompleteBoth: Unit = { - val expected = Set( - ("formatted", Method, "(fmtstr: String): String"), - ("`foo-bar`", Field, "Int"), - ("foo", Field, "Int") - ) code"""object Foo: - | object Bar: - | val foo = 1 - | val `foo-bar` = 2 - | val `bar` = 3 - | - | val x = Bar.fo${m1}""" - .withSource.completion(m1, expected) + | object Bar: + | val foo = 1 + | val `foo-bar` = 2 + | val `bar` = 3 + | + | val x = Bar.fo${m1}""" + .completion( + ("formatted", Method, "(fmtstr: String): String"), + ("`foo-bar`", Field, "Int"), + ("foo", Field, "Int") + ) } @Test def backticksWhenNotNeeded: Unit = { - val expected = Set( - ("`formatted`", Method, "(fmtstr: String): String"), - ("`foo-bar`", Field, "Int"), - ("`foo`", Field, "Int") - ) code"""object Foo: - | object Bar: - | val foo = 1 - | val `foo-bar` = 2 - | - | val x = Bar.`fo${m1}""" - .withSource.completion(m1, expected) + | object Bar: + | val foo = 1 + | val `foo-bar` = 2 + | + | val x = Bar.`fo${m1}""" + .completion( + ("`formatted`", Method, "(fmtstr: String): String"), + ("`foo-bar`", Field, "Int"), + ("`foo`", Field, "Int") + ) } @Test def backticksImported: Unit = { - val expected = Set( - ("`scalaUtilChainingOps`", Method, "[A](a: A): scala.util.ChainingOps[A]"), - ("`synchronized`", Method, "[X0](x$0: X0): X0") - ) - code"""import scala.util.chaining.`s${m1}""" - .withSource.completion(m1, expected) + code"import scala.util.chaining.`s${m1}" + .completion( + ("`scalaUtilChainingOps`", Method, "[A](a: A): scala.util.ChainingOps[A]"), + ("`synchronized`", Method, "[X0](x$0: X0): X0") + ) } @Test def matchTypeCompletions: Unit = { - val expected = Set( - ("fooTest", Method, "(y: Int): Int"), - ) code"""case class Foo(x: Int) { - | def fooTest(y: Int): Int = ??? - |} - |type Elem[X] = X match { - | case Int => Foo - | case Any => X - |} - |def elem[X](x: X): Elem[X] = x match { - | case x: Int => Foo(x) - | case x: Any => x - |} - |object Test: - | elem(1).foo${m1}""" - .withSource.completion(m1, expected) + | def fooTest(y: Int): Int = ??? + |} + |type Elem[X] = X match { + | case Int => Foo + | case Any => X + |} + |def elem[X](x: X): Elem[X] = x match { + | case x: Int => Foo(x) + | case x: Any => x + |} + |object Test: + | elem(1).foo${m1}""" + .completion(("fooTest", Method, "(y: Int): Int")) } @Test def higherKindedMatchTypeDeclaredCompletion: Unit = { - val expected = Set( - ("map", Method, "[B](f: Int => B): Foo[B]"), - ) code"""trait Foo[A] { - | def map[B](f: A => B): Foo[B] = ??? - |} - |case class Bar[F[_]](bar: F[Int]) - |type M[T] = T match { - | case Int => Foo[Int] - |} - |object Test: - | val x = Bar[M](new Foo[Int]{}) - | x.bar.m${m1}""" - .withSource.completion(m1, expected) + | def map[B](f: A => B): Foo[B] = ??? + |} + |case class Bar[F[_]](bar: F[Int]) + |type M[T] = T match { + | case Int => Foo[Int] + |} + |object Test: + | val x = Bar[M](new Foo[Int]{}) + | x.bar.m${m1}""" + .completion(("map", Method, "[B](f: Int => B): Foo[B]")) } @Test def higherKindedMatchTypeLazyCompletion: Unit = { - val expected = Set( - ("map", Method, "[B](f: Int => B): Foo[B]"), - ) code"""trait Foo[A] { - | def map[B](f: A => B): Foo[B] = ??? - |} - |case class Bar[F[_]](bar: F[Int]) - |type M[T] = T match { - | case Int => Foo[Int] - |} - |def foo(x: Bar[M]) = x.bar.m${m1}""" - .withSource.completion(m1, expected) + | def map[B](f: A => B): Foo[B] = ??? + |} + |case class Bar[F[_]](bar: F[Int]) + |type M[T] = T match { + | case Int => Foo[Int] + |} + |def foo(x: Bar[M]) = x.bar.m${m1}""" + .completion(("map", Method, "[B](f: Int => B): Foo[B]")) } // This test is not passing due to https://github.com/lampepfl/dotty/issues/14687 @@ -1190,59 +1157,87 @@ class CompletionTest { // ("mapFoo", Method, "[B](op: Int => B): Foo[B]"), // ) // code"""import scala.language.implicitConversions - // |case class Foo[A](x: A) { - // | def mapFoo[B](op: A => B): Foo[B] = ??? - // |} - // |case class Boo[A](x: A) { - // | def mapBoo[B](op: A => B): Boo[B] = ??? - // |} - // |type M[A] = A match { - // | case Int => Foo[Int] - // |} - // |implicit def fooToBoo[A](x: Foo[A]): Boo[A] = Boo(x.x) - // |case class Bar[F[_]](bar: F[Int]) - // |def foo(x: Bar[M]) = x.bar.m${m1}""" - // .withSource.completion(m1, expected) + // |case class Foo[A](x: A) { + // | def mapFoo[B](op: A => B): Foo[B] = ??? + // |} + // |case class Boo[A](x: A) { + // | def mapBoo[B](op: A => B): Boo[B] = ??? + // |} + // |type M[A] = A match { + // | case Int => Foo[Int] + // |} + // |implicit def fooToBoo[A](x: Foo[A]): Boo[A] = Boo(x.x) + // |case class Bar[F[_]](bar: F[Int]) + // |def foo(x: Bar[M]) = x.bar.m${m1}""" + // .completion(m1, expected) // } @Test def higherKindedMatchTypeExtensionMethodCompletion: Unit = { - val expected = Set( - ("mapFoo", Method, "[B](f: Int => B): Foo[B]"), - ("mapExtensionMethod", Method, "[B](f: Int => B): Foo[B]"), - ) code"""trait Foo[A] { - | def mapFoo[B](f: A => B): Foo[B] = ??? - |} - |extension[A] (x: Foo[A]) { - | def mapExtensionMethod[B](f: A => B): Foo[B] = ??? - |} - |case class Baz[F[_]](baz: F[Int]) - |type M[T] = T match { - | case Int => Foo[Int] - |} - |case class Bar[F[_]](bar: F[Int]) - |def foo(x: Bar[M]) = x.bar.ma${m1}""" - .withSource.completion(m1, expected) + | def mapFoo[B](f: A => B): Foo[B] = ??? + |} + |extension[A] (x: Foo[A]) { + | def mapExtensionMethod[B](f: A => B): Foo[B] = ??? + |} + |case class Baz[F[_]](baz: F[Int]) + |type M[T] = T match { + | case Int => Foo[Int] + |} + |case class Bar[F[_]](bar: F[Int]) + |def foo(x: Bar[M]) = x.bar.ma${m1}""" + .completion( + ("mapFoo", Method, "[B](f: Int => B): Foo[B]"), + ("mapExtensionMethod", Method, "[B](f: Int => B): Foo[B]"), + ) } @Test def packageCompletionsOutsideImport: Unit = { - val expected = Set( - ("java", Module, "java"), - ("javax", Module, "javax"), - ) code"""object Foo { ja${m1}""" - .withSource.completion(m1, expected) + .completion( + ("java", Module, "java"), + ("javax", Module, "javax"), + ) } @Test def topLevelPackagesCompletionsOutsideImport: Unit = { - val expected = Set( - ("example", Module, "example"), - ) code"""package example: | def foo = "" | |def main = exa${m1}""" - .withSource.completion(m1, expected) + .completion(("example", Module, "example")) + } + + @Test def typeAliasCompletions: Unit = { + code"""class Test() { + | def fooTest(x: Int): Unit = ??? + |} + |type TestAlias = Test + |object O: + | val test: TestAlias = new Test() + | test.foo${m1}""" + .completion(("fooTest", Method, "(x: Int): Unit")) + } + + @Test def higherKindedTypeAliasesCompletions: Unit = { + val expected = Set(("fooTest", Method, "(x: Int): Option[Unit]")) + code"""trait Test[F[_]] { + | def fooTest(x: Int): F[Unit] = ??? + |} + | + |type TestAlias[M[_[_]]] = M[Option] + |object O: + | val test: TestAlias[Test] = new Test[Option] {} + | val test2: Test[Option] = new Test[Option] {} + | test.foo${m1} + | test2.foo${m2}""" + .completion(m1, expected) + .completion(m2, expected) + } + + @Test def `???`: Unit = { + code"""object O: + | ???.${m1}""" + .noCompletions() } } diff --git a/language-server/test/dotty/tools/languageserver/DefinitionTest.scala b/language-server/test/dotty/tools/languageserver/DefinitionTest.scala index 4eebe9d40dd0..ddacd0c868e0 100644 --- a/language-server/test/dotty/tools/languageserver/DefinitionTest.scala +++ b/language-server/test/dotty/tools/languageserver/DefinitionTest.scala @@ -85,7 +85,7 @@ class DefinitionTest { code"""object Foo { def foo(${m1}x${m2}: Int) = ${m3}x${m4} foo(${m5}x${m6} = 2) - }""".withSource + }""" .definition(m1 to m2, List(m1 to m2)) .definition(m3 to m4, List(m1 to m2)) .definition(m5 to m6, List(m1 to m2)) @@ -114,7 +114,7 @@ class DefinitionTest { case t: T => t.${m17}foo${m18}("e") } } - }""".withSource + }""" .definition(m1 to m2, List(m1 to m2, m3 to m4, m5 to m6, m7 to m8)) .definition(m3 to m4, List(m1 to m2, m3 to m4)) .definition(m5 to m6, List(m1 to m2, m5 to m6, m7 to m8)) @@ -133,7 +133,7 @@ class DefinitionTest { def foo(${m5}x${m6}: Int): String = foo(${m7}x${m8} = ${m9}x${m10}.toString) foo(${m11}x${m12} = "a") foo(${m13}x${m14} = 2) - }""".withSource + }""" .definition(m1 to m2, List(m1 to m2)) .definition(m3 to m4, List(m1 to m2)) .definition(m5 to m6, List(m5 to m6)) @@ -223,7 +223,7 @@ class DefinitionTest { code"""trait ${m1}Foo${m2} { val x = 0 } class C { def foo = new ${m3}Foo${m4} {} - }""".withSource + }""" .definition(m1 to m2, List(m1 to m2)) .definition(m3 to m4, List(m1 to m2)) } @@ -232,7 +232,7 @@ class DefinitionTest { code"""abstract class ${m1}Foo${m2} { val x = 0 } class C { def foo = new ${m3}Foo${m4} {} - }""".withSource + }""" .definition(m1 to m2, List(m1 to m2)) .definition(m3 to m4, List(m1 to m2)) } @@ -242,7 +242,7 @@ class DefinitionTest { trait ${m3}Bar${m4} class C { def foo = new ${m5}Foo${m6} with ${m7}Bar${m8} {} - }""".withSource + }""" .definition(m1 to m2, List(m1 to m2)) .definition(m3 to m4, List(m3 to m4)) .definition(m5 to m6, List(m1 to m2)) diff --git a/language-server/test/dotty/tools/languageserver/DiagnosticsTest.scala b/language-server/test/dotty/tools/languageserver/DiagnosticsTest.scala index 6b555e15015c..2e9009c011e3 100644 --- a/language-server/test/dotty/tools/languageserver/DiagnosticsTest.scala +++ b/language-server/test/dotty/tools/languageserver/DiagnosticsTest.scala @@ -10,7 +10,7 @@ class DiagnosticsTest { @Test def diagnosticWrongType: Unit = code"""object Test { | val x: Int = $m1"foo"$m2 - |}""".withSource + |}""" .diagnostics(m1, (m1 to m2, """Found: ("foo" : String) |Required: Int""".stripMargin, Error, Some(TypeMismatchID)) @@ -19,7 +19,7 @@ class DiagnosticsTest { @Test def diagnosticMissingLambdaBody: Unit = code"""object Test { | Nil.map(x => x).filter(x$m1 =>$m2)$m3 - |}""".withSource + |}""" .diagnostics(m1, (m2 to m2, "expression expected but ')' found", Error, Some(IllegalStartSimpleExprID)) ) @@ -27,13 +27,13 @@ class DiagnosticsTest { @Test def diagnosticPureExpression: Unit = code"""object Test { | ${m1}1$m2 - |}""".withSource + |}""" .diagnostics(m1, (m1 to m2, "A pure expression does nothing in statement position; you may be omitting necessary parentheses", Warning, Some(PureExpressionInStatementPositionID))) @Test def diagnosticWorksheetPureExpression: Unit = - ws"""${m1}1""".withSource + ws"""${m1}1""" .diagnostics(m1 /* no "pure expression" warning because this is a worksheet */) } diff --git a/language-server/test/dotty/tools/languageserver/DocumentSymbolTest.scala b/language-server/test/dotty/tools/languageserver/DocumentSymbolTest.scala index 81e4379c99eb..9650d99765bb 100644 --- a/language-server/test/dotty/tools/languageserver/DocumentSymbolTest.scala +++ b/language-server/test/dotty/tools/languageserver/DocumentSymbolTest.scala @@ -10,13 +10,14 @@ class DocumentSymbolTest { @Test def withErroneousTree: Unit = code"${m1}class Foo { def }$m2" - .withSource.documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Class)) + .documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Class)) @Test def documentSymbol0: Unit = - code"${m1}class Foo$m2".withSource.documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Class)) + code"${m1}class Foo$m2" + .documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Class)) @Test def documentSymbol1: Unit = - code"${m1}class Foo$m2; ${m3}class Bar$m4".withSource + code"${m1}class Foo$m2; ${m3}class Bar$m4" .documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Class), (m3 to m4).symInfo("Bar", SymbolKind.Class)) @Test def documentSymbol3: Unit = { @@ -28,19 +29,19 @@ class DocumentSymbolTest { } @Test def documentSymbolShowModule: Unit = { - code"""${m1}object Foo${m2}""".withSource + code"""${m1}object Foo${m2}""" .documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Module)) } @Test def documentSymbolShowClassAndCompanion: Unit = { code"""${m1}object Foo${m2} - |${m3}class Foo${m4}""".withSource + |${m3}class Foo${m4}""" .documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Module), (m3 to m4).symInfo("Foo", SymbolKind.Class)) } @Test def documentSymbolSynthetic: Unit = { - code"""${m1}case class Foo(${m3}x: Int${m4})${m2}""".withSource + code"""${m1}case class Foo(${m3}x: Int${m4})${m2}""" .documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Class), (m3 to m4).symInfo("x", SymbolKind.Field, "Foo")) } @@ -49,7 +50,7 @@ class DocumentSymbolTest { code"""${m1}enum Option[${m3}+T${m4}] { ${m5}case Some(${m7}x: T${m8})${m6} ${m9}case None${m10} - }${m2}""".withSource + }${m2}""" .documentSymbol(m1, (m1 to m2).symInfo("Option", SymbolKind.Enum), (m3 to m4).symInfo("T", SymbolKind.TypeParameter, "Option"), (m5 to m6).symInfo("Some", SymbolKind.EnumMember, "Option"), @@ -62,7 +63,7 @@ class DocumentSymbolTest { ${m5}case Red extends Color(0xFF0000)${m6} ${m7}case Green extends Color(0x00FF00)${m8} ${m9}case Blue extends Color(0x0000FF)${m10} - }${m2}""".withSource + }${m2}""" .documentSymbol(m1, (m1 to m2).symInfo("Color", SymbolKind.Enum), (m3 to m4).symInfo("rgb", SymbolKind.Field, "Color"), (m5 to m6).symInfo("Red", SymbolKind.EnumMember, "Color"), @@ -71,24 +72,27 @@ class DocumentSymbolTest { } @Test def documentSymbolTopLevelDef: Unit = - code"${m1}def foo(): Unit = { }${m2}".withSource.documentSymbol(m1, (m1 to m2).symInfo("foo", SymbolKind.Method)) + code"${m1}def foo(): Unit = { }${m2}" + .documentSymbol(m1, (m1 to m2).symInfo("foo", SymbolKind.Method)) @Test def documentSymbolTrait: Unit = - code"${m1}trait Foo(${m3}val x: Int${m4})${m2}".withSource.documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Interface), - (m3 to m4).symInfo("x", SymbolKind.Field, "Foo")) + code"${m1}trait Foo(${m3}val x: Int${m4})${m2}" + .documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Interface), + (m3 to m4).symInfo("x", SymbolKind.Field, "Foo")) @Test def documentSymbolLocalDef: Unit = code"""${m1}def foo(): Unit = { ${m3}def bar(): Unit = { }${m4} ${m5}val x: Int = 0${m6} - }${m2}""".withSource.documentSymbol(m1, (m1 to m2).symInfo("foo", SymbolKind.Method), - (m3 to m4).symInfo("bar", SymbolKind.Method, "foo"), - (m5 to m6).symInfo("x", SymbolKind.Field, "foo") ) + }${m2}""" + .documentSymbol(m1, (m1 to m2).symInfo("foo", SymbolKind.Method), + (m3 to m4).symInfo("bar", SymbolKind.Method, "foo"), + (m5 to m6).symInfo("x", SymbolKind.Field, "foo")) @Test def documentSymbolTypeFields: Unit = code"""${m1}class Foo { ${m3}type T${m4} - }${m2}""".withSource.documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Class), - (m3 to m4).symInfo("T", SymbolKind.TypeParameter, "Foo")) + }${m2}""".documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Class), + (m3 to m4).symInfo("T", SymbolKind.TypeParameter, "Foo")) } diff --git a/language-server/test/dotty/tools/languageserver/HighlightTest.scala b/language-server/test/dotty/tools/languageserver/HighlightTest.scala index 8c8b0a445eda..2a205f0c9787 100644 --- a/language-server/test/dotty/tools/languageserver/HighlightTest.scala +++ b/language-server/test/dotty/tools/languageserver/HighlightTest.scala @@ -8,19 +8,19 @@ class HighlightTest { @Test def valHighlight0: Unit = { val xDef = (m1 to m2).withCode("x") - code"class X { val $xDef = 9 }".withSource + code"class X { val $xDef = 9 }" .highlight(xDef.range, (xDef.range, DocumentHighlightKind.Read)) } @Test def valHighlight1: Unit = { val xDef = (m1 to m2).withCode("x") val xRef = (m3 to m4).withCode("x") - code"class X { val $xDef = 9; $xRef}".withSource + code"class X { val $xDef = 9; $xRef}" .highlight(xRef.range, (xDef.range, DocumentHighlightKind.Read), (xRef.range, DocumentHighlightKind.Read)) } @Test def highlightClass(): Unit = { - code"""class ${m1}Foo${m2} { new ${m3}Foo${m4} }""".withSource + code"""class ${m1}Foo${m2} { new ${m3}Foo${m4} }""" .highlight(m1 to m2, (m1 to m2, DocumentHighlightKind.Read), (m3 to m4, DocumentHighlightKind.Read)) .highlight(m3 to m4, (m1 to m2, DocumentHighlightKind.Read), (m3 to m4, DocumentHighlightKind.Read)) } @@ -28,7 +28,7 @@ class HighlightTest { @Test def importHighlight0: Unit = { code"""object ${m1}Foo${m2} { def ${m5}bar${m6}: Int = 0 } trait Bar { import ${m3}Foo${m4}._; def buzz = ${m7}bar${m8} } - trait Baz { def ${m9}bar${m10}: Int = 1 }""".withSource + trait Baz { def ${m9}bar${m10}: Int = 1 }""" .highlight(m1 to m2, (m1 to m2, DocumentHighlightKind.Read), (m3 to m4, DocumentHighlightKind.Read)) .highlight(m3 to m4, (m1 to m2, DocumentHighlightKind.Read), (m3 to m4, DocumentHighlightKind.Read)) @@ -40,7 +40,7 @@ class HighlightTest { @Test def importHighlight1: Unit = { code"""import ${m1}Foo${m2}._ object ${m3}Foo${m4} { def ${m5}bar${m6}: Int = 0 } - trait Bar { def buzz = ${m7}bar${m8} }""".withSource + trait Bar { def buzz = ${m7}bar${m8} }""" .highlight(m1 to m2, (m1 to m2, DocumentHighlightKind.Read), (m3 to m4, DocumentHighlightKind.Read)) .highlight(m3 to m4, (m1 to m2, DocumentHighlightKind.Read), (m3 to m4, DocumentHighlightKind.Read)) @@ -50,7 +50,7 @@ class HighlightTest { @Test def importHighlight2: Unit = { code"""object ${m1}Foo${m2} { object ${m3}Bar${m4} { object ${m5}Baz${m6} } } - trait Buzz { import ${m7}Foo${m8}.${m9}Bar${m10}.${m11}Baz${m12} }""".withSource + trait Buzz { import ${m7}Foo${m8}.${m9}Bar${m10}.${m11}Baz${m12} }""" .highlight(m1 to m2, (m1 to m2, DocumentHighlightKind.Read), (m7 to m8, DocumentHighlightKind.Read)) .highlight(m3 to m4, (m3 to m4, DocumentHighlightKind.Read), (m9 to m10, DocumentHighlightKind.Read)) @@ -62,7 +62,7 @@ class HighlightTest { @Test def importHighlight3: Unit = { code"""import ${m1}Foo${m2}.${m3}Bar${m4} - object ${m5}Foo${m6} { object ${m7}Bar${m8} }""".withSource + object ${m5}Foo${m6} { object ${m7}Bar${m8} }""" .highlight(m1 to m2, (m1 to m2, DocumentHighlightKind.Read), (m5 to m6, DocumentHighlightKind.Read)) .highlight(m3 to m4, (m3 to m4, DocumentHighlightKind.Read), (m7 to m8, DocumentHighlightKind.Read)) @@ -72,7 +72,7 @@ class HighlightTest { @Test def importHighlightClassAndCompanion: Unit = { code"""object Foo { object ${m1}Bar${m2}; class ${m3}Bar${m4} } - trait Buzz { import Foo.${m5}Bar${m6} }""".withSource + trait Buzz { import Foo.${m5}Bar${m6} }""" .highlight(m1 to m2, (m1 to m2, DocumentHighlightKind.Read), (m5 to m6, DocumentHighlightKind.Read)) .highlight(m3 to m4, (m3 to m4, DocumentHighlightKind.Read), (m5 to m6, DocumentHighlightKind.Read)) .highlight(m5 to m6, (m3 to m4, DocumentHighlightKind.Read), (m5 to m6, DocumentHighlightKind.Read), (m1 to m2, DocumentHighlightKind.Read)) @@ -80,7 +80,7 @@ class HighlightTest { @Test def importHighlightWithRename: Unit = { code"""object ${m1}Foo${m2} { object ${m3}Bar${m4} { object ${m5}Baz${m6} } } - trait Buzz { import ${m7}Foo${m8}.${m9}Bar${m10}.{${m11}Baz${m12} => ${m13}Quux${m14}}""".withSource + trait Buzz { import ${m7}Foo${m8}.${m9}Bar${m10}.{${m11}Baz${m12} => ${m13}Quux${m14}}""" .highlight(m1 to m2, (m1 to m2, DocumentHighlightKind.Read), (m7 to m8, DocumentHighlightKind.Read)) .highlight(m3 to m4, (m3 to m4, DocumentHighlightKind.Read), (m9 to m10, DocumentHighlightKind.Read)) @@ -93,7 +93,7 @@ class HighlightTest { @Test def importHighlightClassAndCompanionWithRename: Unit = { code"""object ${m1}Foo${m2} { object ${m3}Bar${m4}; class ${m5}Bar${m6} } - trait Buzz { import ${m7}Foo${m8}.{${m9}Bar${m10} => ${m11}Baz${m12}} }""".withSource + trait Buzz { import ${m7}Foo${m8}.{${m9}Bar${m10} => ${m11}Baz${m12}} }""" .highlight(m1 to m2, (m1 to m2, DocumentHighlightKind.Read), (m7 to m8, DocumentHighlightKind.Read)) .highlight(m3 to m4, (m3 to m4, DocumentHighlightKind.Read), (m9 to m10, DocumentHighlightKind.Read), (m11 to m12, DocumentHighlightKind.Read)) @@ -105,7 +105,7 @@ class HighlightTest { @Test def importHighlightMembers: Unit = { code"""object Foo { def ${m1}bar${m2} = 2; type ${m3}bar${m4} = fizz; class fizz } - trait Quux { import Foo.{${m5}bar${m6} => ${m7}buzz${m8}} }""".withSource + trait Quux { import Foo.{${m5}bar${m6} => ${m7}buzz${m8}} }""" .highlight(m1 to m2, (m1 to m2, DocumentHighlightKind.Read), (m5 to m6, DocumentHighlightKind.Read), (m7 to m8, DocumentHighlightKind.Read)) .highlight(m3 to m4, (m3 to m4, DocumentHighlightKind.Read), (m5 to m6, DocumentHighlightKind.Read), (m7 to m8, DocumentHighlightKind.Read)) diff --git a/language-server/test/dotty/tools/languageserver/HoverTest.scala b/language-server/test/dotty/tools/languageserver/HoverTest.scala index 5c2a1aa25efe..bbfec815e79a 100644 --- a/language-server/test/dotty/tools/languageserver/HoverTest.scala +++ b/language-server/test/dotty/tools/languageserver/HoverTest.scala @@ -18,24 +18,25 @@ class HoverTest { |$comment""").stripMargin) @Test def hoverOnWhiteSpace0: Unit = - code"$m1 $m2".withSource.hover(m1 to m2, None) + code"$m1 $m2" + .hover(m1 to m2, None) @Test def hoverOnClassShowsDoc: Unit = { - code"""$m1 /** foo */ ${m2}class Foo $m3 $m4""".withSource + code"""$m1 /** foo */ ${m2}class Foo $m3 $m4""" .hover(m1 to m2, None) .hover(m2 to m3, hoverContent("Foo", "foo")) .hover(m3 to m4, None) } @Test def hoverOnClass0: Unit = { - code"""$m1 ${m2}class Foo $m3 $m4""".withSource + code"""$m1 ${m2}class Foo $m3 $m4""" .hover(m1 to m2, None) .hover(m2 to m3, hoverContent("Foo")) .hover(m3 to m4, None) } @Test def hoverOnClass1: Unit = { - code"""$m1 ${m2}class Foo { } $m3 $m4""".withSource + code"""$m1 ${m2}class Foo { } $m3 $m4""" .hover(m1 to m2, None) .hover(m2 to m3, hoverContent("Foo")) .hover(m3 to m4, None) @@ -44,7 +45,7 @@ class HoverTest { @Test def hoverOnValDef0: Unit = { code"""class Foo { | ${m1}val x = ${m2}8$m3; ${m4}x$m5 - |}""".withSource + |}""" .hover(m1 to m2, hoverContent("Int")) .hover(m2 to m3, hoverContent("(8 : Int)")) .hover(m4 to m5, hoverContent("Int")) @@ -53,7 +54,7 @@ class HoverTest { @Test def hoverOnValDef1: Unit = { code"""class Foo { | ${m1}final val x = 8$m2; ${m3}x$m4 - |}""".withSource + |}""" .hover(m1 to m2, hoverContent("(8 : Int)")) .hover(m3 to m4, hoverContent("(8 : Int)")) } @@ -61,7 +62,7 @@ class HoverTest { @Test def hoverOnDefDef0: Unit = { code"""class Foo { | ${m1}def x = ${m2}8$m3; ${m4}x$m5 - |}""".withSource + |}""" .hover(m1 to m2, hoverContent("Int")) .hover(m2 to m3, hoverContent("(8 : Int)")) .hover(m4 to m5, hoverContent("Int")) @@ -70,7 +71,7 @@ class HoverTest { @Test def hoverMissingRef0: Unit = { code"""class Foo { | ${m1}x$m2 - |}""".withSource + |}""" .hover(m1 to m2, None) } @@ -82,7 +83,7 @@ class HoverTest { | def y(): Int = 9 | ${m5}y($m6)$m7 |} - """.withSource + """ .hover(m1 to m2, hoverContent("(\"abc\" : String)")) .hover(m3 to m4, hoverContent("String")) .hover(m5 to m6, hoverContent("(): Int")) @@ -96,7 +97,7 @@ class HoverTest { |class ${m1}Foo${m2} |/** $$Variable */ |class ${m3}Bar${m4} extends Foo - """.withSource + """ .hover(m1 to m2, hoverContent("Foo", "A class: Test")) .hover(m3 to m4, hoverContent("Bar", "Test")) } @@ -123,7 +124,7 @@ class HoverTest { | * @usecase def bar(fizz: Int, buzz: String): Any | */ | def ${m1}bar${m2}[T, U](fizz: Int, buzz: String)(implicit ev: Boolean): Any = ??? - |}""".withSource + |}""" .hover( m1 to m2, hoverContent("[T, U](fizz: Int, buzz: String)(implicit ev: Boolean): Any", @@ -171,7 +172,7 @@ class HoverTest { | def bar: Int = 2 / 1 | /** hello */ | def ${m1}baz${m2}: Int = ??? - |}""".withSource + |}""" .hover(m1 to m2, hoverContent("Int", "hello")) } @@ -184,7 +185,7 @@ class HoverTest { |class annot3 extends scala.annotation.Annotation |class annot4 extends scala.annotation.Annotation |class annot5 extends scala.annotation.Annotation - |""".withSource + |""" .hover(m1 to m2, hoverContent("(1 : Int)")) .hover(m3 to m4, hoverContent("annot1")) .hover(m5 to m6, hoverContent("annot2")) @@ -199,7 +200,7 @@ class HoverTest { | type `🤪` | def ${m1}bar${m2}: → = ??? | def ${m3}baz${m4}: `🤪` = ??? - |}""".withSource + |}""" .hover(m1 to m2, hoverContent("Test.→")) .hover(m3 to m4, hoverContent("Test.🤪")) @@ -208,7 +209,7 @@ class HoverTest { @Test def topLevel: Unit = { code"""package hello |val x: Int = 1 - |val y = ${m1}this${m2}.x""".withSource + |val y = ${m1}this${m2}.x""" // The test framework will place the code above in a virtual file called Source0.scala, // sp the top-level definitions should be enclosed in an object called `Source0$package`. .hover(m1 to m2, hoverContent("(hello.Source0$package : hello.Source0$package.type)")) @@ -219,27 +220,27 @@ class HoverTest { |object SimpleEnum: | enum Color: | case ${m1}Red${m2}, Green, Blue - |""".withSource + |""" .hover(m1 to m2, hoverContent("example.SimpleEnum.Color")) } - + @Test def enums: Unit = { code"""|package example |enum TestEnum3: | case ${m1}A${m2} // no tooltip | - |""".withSource + |""" .hover(m1 to m2, hoverContent("example.TestEnum3")) } - + @Test def tuple: Unit = { code"""|object A: - | val (${m1}first${m2}, second) = (1.0, 2)""".withSource + | val (${m1}first${m2}, second) = (1.0, 2)""" .hover(m1 to m2, hoverContent("Double")) } @Test def multiAssigment: Unit = { - code"""|val ${m1}x${m2}, ${m3}y${m4} = 42.0""".withSource + code"""|val ${m1}x${m2}, ${m3}y${m4} = 42.0""" .hover(m1 to m2, hoverContent("Double")) .hover(m3 to m4, hoverContent("Double")) } diff --git a/language-server/test/dotty/tools/languageserver/ImplementationTest.scala b/language-server/test/dotty/tools/languageserver/ImplementationTest.scala index cb5a8faaf18c..0ef85bf63d64 100644 --- a/language-server/test/dotty/tools/languageserver/ImplementationTest.scala +++ b/language-server/test/dotty/tools/languageserver/ImplementationTest.scala @@ -12,7 +12,7 @@ class ImplementationTest { } class B extends A { override def ${m3}foo${m4}(x: Int): String = "" - }""".withSource + }""" .implementation(m1 to m2, List(m3 to m4)) .implementation(m3 to m4, List(m3 to m4)) } @@ -26,7 +26,7 @@ class ImplementationTest { } class C extends B { override def ${m5}foo${m6}(x: Int): String = "" - }""".withSource + }""" .implementation(m1 to m2, List(m3 to m4, m5 to m6)) .implementation(m3 to m4, List(m3 to m4, m5 to m6)) .implementation(m5 to m6, List(m5 to m6)) @@ -34,7 +34,7 @@ class ImplementationTest { @Test def extendsTrait: Unit = { code"""trait ${m1}A${m2} - class ${m3}B${m4} extends ${m5}A${m6}""".withSource + class ${m3}B${m4} extends ${m5}A${m6}""" .implementation(m1 to m2, List(m3 to m4)) .implementation(m3 to m4, List(m3 to m4)) .implementation(m5 to m6, List(m3 to m4)) @@ -42,7 +42,7 @@ class ImplementationTest { @Test def extendsClass: Unit = { code"""class ${m1}A${m2} - class ${m3}B${m4} extends ${m5}A${m6}""".withSource + class ${m3}B${m4} extends ${m5}A${m6}""" .implementation(m1 to m2, List(m1 to m2, m3 to m4)) .implementation(m3 to m4, List(m3 to m4)) .implementation(m5 to m6, List(m1 to m2, m3 to m4)) @@ -50,7 +50,7 @@ class ImplementationTest { @Test def objExtendsTrait: Unit = { code"""trait ${m1}A${m2} - object ${m3}B${m4} extends ${m5}A${m6}""".withSource + object ${m3}B${m4} extends ${m5}A${m6}""" .implementation(m1 to m2, List(m3 to m4)) .implementation(m3 to m4, List(m3 to m4)) .implementation(m5 to m6, List(m3 to m4)) @@ -58,7 +58,7 @@ class ImplementationTest { @Test def defineAbstractType: Unit = { code"""trait A { type ${m1}T${m2} } - trait B extends A { type ${m3}T${m4} = Int }""".withSource + trait B extends A { type ${m3}T${m4} = Int }""" .implementation(m1 to m2, List(m3 to m4)) .implementation(m3 to m4, List(m3 to m4)) } @@ -67,7 +67,7 @@ class ImplementationTest { code"""trait A { trait ${m1}AA${m2} } class B extends A { class ${m3}AB${m4} extends ${m5}AA${m6} - }""".withSource + }""" .implementation(m1 to m2, List(m3 to m4)) .implementation(m3 to m4, List(m3 to m4)) .implementation(m5 to m6, List(m3 to m4)) diff --git a/language-server/test/dotty/tools/languageserver/ReferencesTest.scala b/language-server/test/dotty/tools/languageserver/ReferencesTest.scala index fae7c29bd378..f898ccbcdfe5 100644 --- a/language-server/test/dotty/tools/languageserver/ReferencesTest.scala +++ b/language-server/test/dotty/tools/languageserver/ReferencesTest.scala @@ -7,20 +7,21 @@ import dotty.tools.languageserver.util.Code._ class ReferencesTest { @Test def valNoReferences0: Unit = - code"class X { val ${m1}x$m2 = 9 }".withSource.references(m1 to m2, Nil) + code"class X { val ${m1}x$m2 = 9 }" + .references(m1 to m2, Nil) @Test def valReferences0: Unit = { - code"class X { val ${m1}x$m2 = 9; ${m3}x$m4; ${m5}x$m6 }".withSource + code"class X { val ${m1}x$m2 = 9; ${m3}x$m4; ${m5}x$m6 }" .references(m1 to m2, List(m3 to m4, m5 to m6)) } @Test def valReferences1: Unit = { - code"class X { val ${m1}x$m2 = 9; ${m3}x$m4; ${m5}x$m6 }".withSource + code"class X { val ${m1}x$m2 = 9; ${m3}x$m4; ${m5}x$m6 }" .references(m1 to m2, List(m1 to m2, m3 to m4, m5 to m6), withDecl = true) } @Test def classReference0: Unit = { - code"class ${m1}Foo${m2} { val a = new ${m3}Foo${m4} }".withSource + code"class ${m1}Foo${m2} { val a = new ${m3}Foo${m4} }" .references(m1 to m2, List(m1 to m2, m3 to m4), withDecl = true) .references(m1 to m2, List(m3 to m4), withDecl = false) .references(m3 to m4, List(m1 to m2, m3 to m4), withDecl = true) @@ -28,7 +29,7 @@ class ReferencesTest { } @Test def classReference1: Unit = { - code"class ${m1}Foo${m2}(x: Int) { val a = new ${m3}Foo${m4}(1) }".withSource + code"class ${m1}Foo${m2}(x: Int) { val a = new ${m3}Foo${m4}(1) }" .references(m1 to m2, List(m1 to m2, m3 to m4), withDecl = true) .references(m1 to m2, List(m3 to m4), withDecl = false) .references(m3 to m4, List(m1 to m2, m3 to m4), withDecl = true) @@ -37,7 +38,7 @@ class ReferencesTest { @Test def classReferenceCompanion: Unit = { code"""class ${m1}Foo${m2}(x: Any) - |object ${m3}Foo${m4} { val bar = new ${m5}Foo${m6}(${m7}Foo${m8}) }""".withSource + |object ${m3}Foo${m4} { val bar = new ${m5}Foo${m6}(${m7}Foo${m8}) }""" .references(m1 to m2, List(m1 to m2, m5 to m6), withDecl = true) .references(m1 to m2, List(m5 to m6), withDecl = false) .references(m3 to m4, List(m3 to m4, m7 to m8), withDecl = true) @@ -52,7 +53,7 @@ class ReferencesTest { code"""trait ${m1}Foo${m2} |object O { | val foo = new ${m3}Foo${m4} {} - |}""".withSource + |}""" .references(m1 to m2, List(m1 to m2, m3 to m4), withDecl = true) .references(m1 to m2, List(m3 to m4), withDecl = false) .references(m3 to m4, List(m1 to m2, m3 to m4), withDecl = true) @@ -220,7 +221,7 @@ class ReferencesTest { @Test def importReference1: Unit = { code"""import ${m1}Foo${m2}._ |object ${m3}Foo${m4} { def ${m5}bar${m6}: Int = 0 } - |trait Bar { def buzz = ${m7}bar${m8} }""".withSource + |trait Bar { def buzz = ${m7}bar${m8} }""" .references(m1 to m2, List(m1 to m2, m3 to m4), withDecl = true) .references(m1 to m2, List(m1 to m2), withDecl = false) @@ -234,25 +235,25 @@ class ReferencesTest { @Test def importReference2: Unit = { code"""object ${m1}Foo${m2} { object ${m3}Bar${m4} { object ${m5}Baz${m6} } } - trait Buzz { import ${m7}Foo${m8}.${m9}Bar${m10}.${m11}Baz${m12} }""".withSource - - .references(m1 to m2, List(m1 to m2, m7 to m8), withDecl = true) - .references(m1 to m2, List(m7 to m8), withDecl = false) - .references(m3 to m4, List(m3 to m4, m9 to m10), withDecl = true) - .references(m3 to m4, List(m9 to m10), withDecl = false) - .references(m5 to m6, List(m5 to m6, m11 to m12), withDecl = true) - .references(m5 to m6, List(m11 to m12), withDecl = false) - .references(m7 to m8, List(m1 to m2, m7 to m8), withDecl = true) - .references(m7 to m8, List(m7 to m8), withDecl = false) - .references(m9 to m10, List(m3 to m4, m9 to m10), withDecl = true) - .references(m9 to m10, List(m9 to m10), withDecl = false) - .references(m11 to m12, List(m5 to m6, m11 to m12), withDecl = true) - .references(m11 to m12, List(m11 to m12), withDecl = false) + trait Buzz { import ${m7}Foo${m8}.${m9}Bar${m10}.${m11}Baz${m12} }""" + + .references(m1 to m2, List(m1 to m2, m7 to m8), withDecl = true) + .references(m1 to m2, List(m7 to m8), withDecl = false) + .references(m3 to m4, List(m3 to m4, m9 to m10), withDecl = true) + .references(m3 to m4, List(m9 to m10), withDecl = false) + .references(m5 to m6, List(m5 to m6, m11 to m12), withDecl = true) + .references(m5 to m6, List(m11 to m12), withDecl = false) + .references(m7 to m8, List(m1 to m2, m7 to m8), withDecl = true) + .references(m7 to m8, List(m7 to m8), withDecl = false) + .references(m9 to m10, List(m3 to m4, m9 to m10), withDecl = true) + .references(m9 to m10, List(m9 to m10), withDecl = false) + .references(m11 to m12, List(m5 to m6, m11 to m12), withDecl = true) + .references(m11 to m12, List(m11 to m12), withDecl = false) } @Test def importReference3: Unit = { code"""import ${m1}Foo${m2}.${m3}Bar${m4} - object ${m5}Foo${m6} { object ${m7}Bar${m8} }""".withSource + object ${m5}Foo${m6} { object ${m7}Bar${m8} }""" .references(m1 to m2, List(m1 to m2, m5 to m6), withDecl = true) .references(m1 to m2, List(m1 to m2), withDecl = false) @@ -266,7 +267,7 @@ class ReferencesTest { @Test def importReferenceClassAndCompanion: Unit = { code"""object Foo { object ${m1}Bar${m2}; class ${m3}Bar${m4} } - |trait Buzz { import Foo.${m5}Bar${m6} }""".withSource + |trait Buzz { import Foo.${m5}Bar${m6} }""" .references(m1 to m2, List(m1 to m2, m5 to m6), withDecl = true) .references(m1 to m2, List(m5 to m6), withDecl = false) .references(m3 to m4, List(m3 to m4, m5 to m6), withDecl = true) @@ -277,27 +278,27 @@ class ReferencesTest { @Test def importReferenceWithRename: Unit = { code"""object ${m1}Foo${m2} { object ${m3}Bar${m4} { object ${m5}Baz${m6} } } - |trait Buzz { import ${m7}Foo${m8}.${m9}Bar${m10}.{${m11}Baz${m12} => ${m13}Quux${m14}}""".withSource - - .references(m1 to m2, List(m1 to m2, m7 to m8), withDecl = true) - .references(m1 to m2, List(m7 to m8), withDecl = false) - .references(m3 to m4, List(m3 to m4, m9 to m10), withDecl = true) - .references(m3 to m4, List(m9 to m10), withDecl = false) - .references(m5 to m6, List(m5 to m6, m11 to m12, m13 to m14), withDecl = true) - .references(m5 to m6, List(m11 to m12, m13 to m14), withDecl = false) - .references(m7 to m8, List(m1 to m2, m7 to m8), withDecl = true) - .references(m7 to m8, List(m7 to m8), withDecl = false) - .references(m9 to m10, List(m3 to m4, m9 to m10), withDecl = true) - .references(m9 to m10, List(m9 to m10), withDecl = false) - .references(m11 to m12, List(m5 to m6, m11 to m12, m13 to m14), withDecl = true) - .references(m11 to m12, List(m11 to m12, m13 to m14), withDecl = false) - .references(m13 to m14, List(m5 to m6, m11 to m12, m13 to m14), withDecl = true) - .references(m13 to m14, List(m11 to m12, m13 to m14), withDecl = false) + |trait Buzz { import ${m7}Foo${m8}.${m9}Bar${m10}.{${m11}Baz${m12} => ${m13}Quux${m14}}""" + + .references(m1 to m2, List(m1 to m2, m7 to m8), withDecl = true) + .references(m1 to m2, List(m7 to m8), withDecl = false) + .references(m3 to m4, List(m3 to m4, m9 to m10), withDecl = true) + .references(m3 to m4, List(m9 to m10), withDecl = false) + .references(m5 to m6, List(m5 to m6, m11 to m12, m13 to m14), withDecl = true) + .references(m5 to m6, List(m11 to m12, m13 to m14), withDecl = false) + .references(m7 to m8, List(m1 to m2, m7 to m8), withDecl = true) + .references(m7 to m8, List(m7 to m8), withDecl = false) + .references(m9 to m10, List(m3 to m4, m9 to m10), withDecl = true) + .references(m9 to m10, List(m9 to m10), withDecl = false) + .references(m11 to m12, List(m5 to m6, m11 to m12, m13 to m14), withDecl = true) + .references(m11 to m12, List(m11 to m12, m13 to m14), withDecl = false) + .references(m13 to m14, List(m5 to m6, m11 to m12, m13 to m14), withDecl = true) + .references(m13 to m14, List(m11 to m12, m13 to m14), withDecl = false) } @Test def importReferenceClassAndCompanionWithRename: Unit = { code"""object ${m1}Foo${m2} { object ${m3}Bar${m4}; class ${m5}Bar${m6} } - |trait Buzz { import ${m7}Foo${m8}.{${m9}Bar${m10} => ${m11}Baz${m12}} }""".withSource + |trait Buzz { import ${m7}Foo${m8}.{${m9}Bar${m10} => ${m11}Baz${m12}} }""" .references(m1 to m2, List(m1 to m2, m7 to m8), withDecl = true) .references(m1 to m2, List(m7 to m8), withDecl = false) @@ -315,16 +316,16 @@ class ReferencesTest { @Test def importReferenceMembers: Unit = { code"""object Foo { def ${m1}bar${m2} = 2; type ${m3}bar${m4} = fizz; class fizz } - |trait Quux { import Foo.{${m5}bar${m6} => ${m7}buzz${m8}} }""".withSource - - .references(m1 to m2, List(m1 to m2, m5 to m6, m7 to m8), withDecl = true) - .references(m1 to m2, List(m5 to m6, m7 to m8), withDecl = false) - .references(m3 to m4, List(m3 to m4, m5 to m6, m7 to m8), withDecl = true) - .references(m3 to m4, List(m5 to m6, m7 to m8), withDecl = false) - .references(m5 to m6, List(m1 to m2, m3 to m4, m5 to m6, m7 to m8), withDecl = true) - .references(m5 to m6, List(m5 to m6, m7 to m8), withDecl = false) - .references(m7 to m8, List(m1 to m2, m3 to m4, m5 to m6, m7 to m8), withDecl = true) - .references(m7 to m8, List(m5 to m6, m7 to m8), withDecl = false) + |trait Quux { import Foo.{${m5}bar${m6} => ${m7}buzz${m8}} }""" + + .references(m1 to m2, List(m1 to m2, m5 to m6, m7 to m8), withDecl = true) + .references(m1 to m2, List(m5 to m6, m7 to m8), withDecl = false) + .references(m3 to m4, List(m3 to m4, m5 to m6, m7 to m8), withDecl = true) + .references(m3 to m4, List(m5 to m6, m7 to m8), withDecl = false) + .references(m5 to m6, List(m1 to m2, m3 to m4, m5 to m6, m7 to m8), withDecl = true) + .references(m5 to m6, List(m5 to m6, m7 to m8), withDecl = false) + .references(m7 to m8, List(m1 to m2, m3 to m4, m5 to m6, m7 to m8), withDecl = true) + .references(m7 to m8, List(m5 to m6, m7 to m8), withDecl = false) } @Test def multipleImportsPerLineWithRename: Unit = { diff --git a/language-server/test/dotty/tools/languageserver/RenameTest.scala b/language-server/test/dotty/tools/languageserver/RenameTest.scala index 52da664cc1c1..6968cf155e00 100644 --- a/language-server/test/dotty/tools/languageserver/RenameTest.scala +++ b/language-server/test/dotty/tools/languageserver/RenameTest.scala @@ -10,7 +10,7 @@ class RenameTest { @Test def rename0: Unit = { def testRenameFrom(m: CodeMarker) = - code"class ${m1}Foo$m2 { new ${m3}Foo$m4 }".withSource.rename(m, "Bar", Set(m1 to m2, m3 to m4)) + code"class ${m1}Foo$m2 { new ${m3}Foo$m4 }".rename(m, "Bar", Set(m1 to m2, m3 to m4)) testRenameFrom(m1) testRenameFrom(m3) } diff --git a/language-server/test/dotty/tools/languageserver/SignatureHelpTest.scala b/language-server/test/dotty/tools/languageserver/SignatureHelpTest.scala index 2f76491ce2c6..bc4facd7b88f 100644 --- a/language-server/test/dotty/tools/languageserver/SignatureHelpTest.scala +++ b/language-server/test/dotty/tools/languageserver/SignatureHelpTest.scala @@ -13,7 +13,7 @@ class SignatureHelpTest { S("codePointAt", Nil, List(List(P("x$0", "Int"))), Some("Int")) code"""object O { "hello".codePointAt($m1) - }""".withSource + }""" .signatureHelp(m1, List(signature), Some(0), 0) } @@ -26,7 +26,7 @@ class SignatureHelpTest { code"""object O { List($m1) List(1, 2, 3).map($m2) - }""".withSource + }""" .signatureHelp(m1, List(applySig), Some(0), 0) .signatureHelp(m2, List(mapSig), Some(0), 0) } @@ -52,7 +52,7 @@ class SignatureHelpTest { foo2($m2) foo3($m3) foo4($m4) - }""".withSource + }""" .signatureHelp(m1, List(foo1Sig), Some(0), 0) .signatureHelp(m2, List(foo2Sig), Some(0), 0) .signatureHelp(m3, List(foo3Sig), Some(0), 0) @@ -66,7 +66,7 @@ class SignatureHelpTest { def foo(param0: Int): Int = ??? foo($m1) foo(0$m2) - }""".withSource + }""" .signatureHelp(m1, List(signature), Some(0), 0) .signatureHelp(m2, List(signature), Some(0), 0) } @@ -78,7 +78,7 @@ class SignatureHelpTest { foo($m1) foo(0, $m2) foo(0, "$m3") - }""".withSource + }""" .signatureHelp(m1, List(signature), Some(0), 0) .signatureHelp(m2, List(signature), Some(0), 1) .signatureHelp(m3, List(signature), Some(0), 1) @@ -94,7 +94,7 @@ class SignatureHelpTest { foo($m1) foo(0$m2) foo(""$m3) - }""".withSource + }""" .signatureHelp(m1, List(sig0, sig1), None, 0) .signatureHelp(m2, List(sig0, sig1), Some(0), 0) .signatureHelp(m3, List(sig0, sig1), Some(1), 0) @@ -111,7 +111,7 @@ class SignatureHelpTest { foo(""$m3) foo(0, $m4) foo("", $m5) - }""".withSource + }""" .signatureHelp(m1, List(sig0, sig1), None, 0) .signatureHelp(m2, List(sig0, sig1), Some(0), 0) .signatureHelp(m3, List(sig0, sig1), Some(1), 0) @@ -136,7 +136,7 @@ class SignatureHelpTest { foo(0, 0$m6) foo(0, ""$m7) foo("", 0$m8) - }""".withSource + }""" .signatureHelp(m1, sigs, None, 0) .signatureHelp(m2, sigs, None, 0) .signatureHelp(m3, sigs, Some(2), 0) @@ -156,7 +156,7 @@ class SignatureHelpTest { foo($m1) foo(""$m2) foo("")($m3) - }""".withSource + }""" .signatureHelp(m1, List(sig0, sig1), None, 0) .signatureHelp(m2, List(sig0, sig1), None, 0) .signatureHelp(m3, List(sig0, sig1), Some(1), 1) @@ -179,7 +179,7 @@ class SignatureHelpTest { foo(1, 2)($m3) foo(1, 2)(3)($m4) foo(1, 2)(3)(4, $m5) - }""".withSource + }""" .signatureHelp(m1, List(signature), Some(0), 0) .signatureHelp(m2, List(signature), Some(0), 1) .signatureHelp(m3, List(signature), Some(0), 2) @@ -201,7 +201,7 @@ class SignatureHelpTest { foo($m1) foo(1, $m2) foo(1, 2)($m3) - }""".withSource + }""" .signatureHelp(m1, List(signature), Some(0), 0) .signatureHelp(m2, List(signature), Some(0), 1) .signatureHelp(m3, List(signature), Some(0), 2) @@ -218,7 +218,7 @@ class SignatureHelpTest { code"""object O { def foo[M[X], T[Z] <: M[Z], U >: T](p0: M[Int], p1: T[Int], p2: U): Int = ??? foo($m1) - }""".withSource + }""" .signatureHelp(m1, List(signature), Some(0), 0) } @@ -236,7 +236,7 @@ class SignatureHelpTest { new Foo($m1) new Foo(0, $m2) new Foo(0, "hello")($m3) - }""".withSource + }""" .signatureHelp(m1, List(signature), Some(0), 0) .signatureHelp(m2, List(signature), Some(0), 1) .signatureHelp(m3, List(signature), Some(0), 2) @@ -266,7 +266,7 @@ class SignatureHelpTest { new Foo(0, $m2) new Foo(0, "")($m3) new Foo(0, 0$m4) - }""".withSource + }""" .signatureHelp(m1, List(sig0, sig1), None, 0) .signatureHelp(m2, List(sig0, sig1), None, 1) .signatureHelp(m3, List(sig0, sig1), Some(0), 2) @@ -302,7 +302,7 @@ class SignatureHelpTest { new Foo(0, ""$m5) new Foo(true, $m6) new Foo(true, ???$m7) - }""".withSource + }""" .signatureHelp(m1, signatures, None, 0) .signatureHelp(m2, signatures, Some(0), 0) .signatureHelp(m3, signatures, Some(1), 0) @@ -327,7 +327,7 @@ class SignatureHelpTest { new Foo(???, $m2) new Foo(???, ???, $m3) new Foo(???, ???, ???)($m4) - }""".withSource + }""" .signatureHelp(m1, List(signature), Some(0), 0) .signatureHelp(m2, List(signature), Some(0), 1) .signatureHelp(m3, List(signature), Some(0), 2) @@ -338,7 +338,7 @@ class SignatureHelpTest { code"""object O { /** Hello, world! */ def foo(param0: Int): Int = 0 foo($m1) - }""".withSource + }""" .signatureHelp(m1, List(S("foo", Nil, List(List(P("param0", "Int"))), Some("Int"), Some("Hello, world!"))), None, 0) } @@ -353,7 +353,7 @@ class SignatureHelpTest { | */ | def buzz(fizz: Int, bar: Int): Int = ??? | buzz($m1) - |}""".withSource + |}""" .signatureHelp(m1, List( S("buzz", Nil, List(List( P("fizz", "Int", Some("The fizz to buzz")), @@ -361,14 +361,14 @@ class SignatureHelpTest { )), Some("Int"), Some("Buzzes a fizz up to bar")) ), None, 0) } - + @Test def unapplyMethod: Unit = { code"""|object Main { | Option(1) match { | case Some(${m1}) => | } |}""" - .withSource + .signatureHelp(m1, List( S("unapply[A]", Nil, List(List( P("x$0", "Some[A]", None), @@ -388,7 +388,7 @@ class SignatureHelpTest { | case Opt(${m1}) => | } |}""" - .withSource + .signatureHelp(m1, List( S("unapply[A]", Nil, List( List( @@ -400,7 +400,7 @@ class SignatureHelpTest { List( P("x$3", "Int", None, isImplicit = true) ) - ), + ), Some("Option[A]"), None) ), None, 1) } @@ -417,7 +417,7 @@ class SignatureHelpTest { | case Opt(${m1}) => | } |}""" - .withSource + .signatureHelp(m1, List( S("unapply[A]", Nil, List( List( @@ -429,7 +429,7 @@ class SignatureHelpTest { List( P("a", "Option[A]", None), ) - ), + ), Some("Option[A]"), None) ), None, 2) } diff --git a/language-server/test/dotty/tools/languageserver/SymbolTest.scala b/language-server/test/dotty/tools/languageserver/SymbolTest.scala index ff40223434fc..6d3ba86be48a 100644 --- a/language-server/test/dotty/tools/languageserver/SymbolTest.scala +++ b/language-server/test/dotty/tools/languageserver/SymbolTest.scala @@ -29,13 +29,13 @@ class SymbolTest { } @Test def symbolShowModule: Unit = { - code"""object ${m1}Foo${m2}""".withSource + code"""object ${m1}Foo${m2}""" .symbol("Foo", (m1 to m2).symInfo("Foo", SymbolKind.Module)) } @Test def symbolShowClassAndCompanion: Unit = { code"""object ${m1}Foo${m2} - |class ${m3}Foo${m4}""".withSource + |class ${m3}Foo${m4}""" .symbol("Foo", (m1 to m2).symInfo("Foo", SymbolKind.Module), (m3 to m4).symInfo("Foo", SymbolKind.Class)) } @@ -55,10 +55,10 @@ class SymbolTest { @Test def noLocalSymbols: Unit = { code"""object O { - def foo = { - val hello = 0 - } - }""".withSource + | def foo = { + | val hello = 0 + | } + |}""" .symbol("hello") } } diff --git a/language-server/test/dotty/tools/languageserver/WorksheetTest.scala b/language-server/test/dotty/tools/languageserver/WorksheetTest.scala index 1b5972287659..da7c7bceefd6 100644 --- a/language-server/test/dotty/tools/languageserver/WorksheetTest.scala +++ b/language-server/test/dotty/tools/languageserver/WorksheetTest.scala @@ -13,20 +13,20 @@ import java.lang.System.{lineSeparator => nl} class WorksheetTest { @Test def runExpression: Unit = { - ws"${m1}2 + 2${m2}".withSource + ws"${m1}2 + 2${m2}" .run(m1, ((m1 to m2), "val res0: Int = 4")) } @Test def runSimpleVal: Unit = { - ws"${m1}val foo = 123${m2}".withSource + ws"${m1}val foo = 123${m2}" .run(m1, ((m1 to m2), "val foo: Int = 123")) } @Test def usePreviousDefinition: Unit = { ws"""${m1}val foo = 123${m2} - ${m3}val bar = foo + 1${m4}""".withSource + ${m3}val bar = foo + 1${m4}""" .run(m1, ((m1 to m2), "val foo: Int = 123"), ((m3 to m4), "val bar: Int = 124")) @@ -34,7 +34,7 @@ class WorksheetTest { @Test def defineObject: Unit = { ws"""${m1}def foo(x: Int) = x + 1${m2} - ${m3}foo(1)${m4}""".withSource + ${m3}foo(1)${m4}""" .run(m1, ((m1 to m2), "def foo(x: Int): Int"), ((m3 to m4), "val res0: Int = 2")) @@ -42,7 +42,7 @@ class WorksheetTest { @Test def defineCaseClass: Unit = { ws"""${m1}case class Foo(x: Int)${m2} - |${m3}Foo(1)${m4}""".withSource + |${m3}Foo(1)${m4}""" .run(m1, ((m1 to m2), "// defined case class Foo"), ((m3 to m4), "val res0: Foo = Foo(1)")) @@ -52,7 +52,7 @@ class WorksheetTest { ws"""${m1}class Foo(x: Int) { override def toString: String = "Foo" }${m2} - ${m3}new Foo(1)${m4}""".withSource + ${m3}new Foo(1)${m4}""" .run(m1, ((m1 to m2), "// defined class Foo"), ((m3 to m4), "val res0: Foo = Foo")) @@ -61,7 +61,7 @@ class WorksheetTest { @Test def defineAnonymousClass0: Unit = { ws"""${m1}new { override def toString: String = "Foo" - }${m2}""".withSource + }${m2}""" .run(m1, ((m1 to m2), "val res0: Object = Foo")) } @@ -71,7 +71,7 @@ class WorksheetTest { |${m3}trait Bar${m4} |${m5}new Foo with Bar { | override def toString: String = "Foo" - |}${m6}""".withSource + |}${m6}""" .run(m1, ((m1 to m2), "// defined class Foo"), ((m3 to m4), "// defined trait Bar"), @@ -79,7 +79,7 @@ class WorksheetTest { } @Test def produceMultilineOutput: Unit = { - ws"""${m1}1 to 3 foreach println${m2}""".withSource + ws"""${m1}1 to 3 foreach println${m2}""" .run(m1, ((m1 to m2), s"1${nl}2${nl}3")) } @@ -88,14 +88,14 @@ class WorksheetTest { ws"""${m1}1 + 2 match { case x if x % 2 == 0 => "even" case _ => "odd" - }${m2}""".withSource + }${m2}""" .run(m1, ((m1 to m2), "val res0: String = odd")) } @Test def evaluationException: Unit = { ws"""${m1}val foo = 1 / 0${m2} - ${m3}val bar = 2${m4}""".withSource + ${m3}val bar = 2${m4}""" .runNonStrict(m1, ((m1 to m2), "java.lang.ArithmeticException: / by zero"), ((m3 to m4), "val bar: Int = 2")) @@ -104,7 +104,7 @@ class WorksheetTest { @Test def worksheetCompletion(): Unit = { ws"""class Foo { def bar = 123 } val x = new Foo - x.b${m1}""".withSource + x.b${m1}""" .completion(m1, Set(("bar", CompletionItemKind.Method, "=> Int"))) } @@ -160,7 +160,7 @@ class WorksheetTest { @Test def worksheetHighlight(): Unit = { ws"""class ${m1}Foo${m2} { def ${m3}bar${m4} = 123 } val x = new ${m5}Foo${m6} - x.${m7}bar${m8}""".withSource + x.${m7}bar${m8}""" .highlight(m1 to m2, (m1 to m2, DocumentHighlightKind.Read), (m5 to m6, DocumentHighlightKind.Read)) .highlight(m3 to m4, (m3 to m4, DocumentHighlightKind.Read), (m7 to m8, DocumentHighlightKind.Read)) .highlight(m5 to m6, (m1 to m2, DocumentHighlightKind.Read), (m5 to m6, DocumentHighlightKind.Read)) @@ -175,7 +175,7 @@ class WorksheetTest { @Test def worksheetHover(): Unit = { ws"""/** A class */ class ${m1}Foo${m2} { /** A method */ def ${m3}bar${m4} = 123 } val x = new ${m5}Foo${m6} - x.${m7}bar${m8}""".withSource + x.${m7}bar${m8}""" .hover(m1 to m2, hoverContent(s"${WorksheetWrapper}.Foo", "A class")) .hover(m3 to m4, hoverContent("Int", "A method")) .hover(m5 to m6, hoverContent(s"${WorksheetWrapper}.Foo", "A class")) @@ -185,7 +185,7 @@ class WorksheetTest { @Test def worksheetDocumentSymbol(): Unit = { ws"""${m1}class Foo { ${m3}def bar = 123${m4} - }${m2}""".withSource + }${m2}""" .documentSymbol(m1, (m1 to m2).symInfo("Foo", SymbolKind.Class, WorksheetWrapper.moduleClassName.stripModuleClassSuffix.toString), (m3 to m4).symInfo("bar", SymbolKind.Method, "Foo")) } @@ -205,20 +205,20 @@ class WorksheetTest { ws"""${m1}val foo = 1 val bar = 2 while (true) {} - val baz = 3""".withSource + val baz = 3""" .cancelRun(m1, afterMs = 5000) } @Test def systemExit(): Unit = { ws"""${m1}println("Hello, world!")${m2} System.exit(0) - println("Goodbye!")""".withSource + println("Goodbye!")""" .run(m1, ((m1 to m2), "Hello, world!")) } @Test def outputOnStdErr(): Unit = { - ws"""${m1}System.err.println("Oh no")${m2}""".withSource + ws"""${m1}System.err.println("Oh no")${m2}""" .run(m1, ((m1 to m2), "Oh no")) } diff --git a/language-server/test/dotty/tools/languageserver/util/Code.scala b/language-server/test/dotty/tools/languageserver/util/Code.scala index 9d9bc5f7c291..7eb2d377cb54 100644 --- a/language-server/test/dotty/tools/languageserver/util/Code.scala +++ b/language-server/test/dotty/tools/languageserver/util/Code.scala @@ -134,6 +134,13 @@ object Code { } + object SourceWithPositions { + import scala.language.implicitConversions + + implicit def sourceWithPositionsToCodeTester(scalaSource: SourceWithPositions): CodeTester = + scalaSource.withSource + } + /** * A virtual Scala source file where several markers have been set. * diff --git a/language-server/test/dotty/tools/languageserver/util/CodeTester.scala b/language-server/test/dotty/tools/languageserver/util/CodeTester.scala index 6deaa3254e35..936286cf8879 100644 --- a/language-server/test/dotty/tools/languageserver/util/CodeTester.scala +++ b/language-server/test/dotty/tools/languageserver/util/CodeTester.scala @@ -4,15 +4,12 @@ import dotty.tools.languageserver.util.Code._ import dotty.tools.languageserver.util.actions._ import dotty.tools.languageserver.util.embedded.CodeMarker import dotty.tools.languageserver.util.server.{TestFile, TestServer} - import dotty.tools.dotc.reporting.ErrorMessageID import dotty.tools.dotc.util.Signatures.Signature import org.eclipse.lsp4j.{ CompletionItem, CompletionItemKind, DocumentHighlightKind, Diagnostic, DiagnosticSeverity } - import org.junit.Assert.assertEquals -import org.junit.Assert.assertEquals /** * Simulates an LSP client for test in a project defined by `sources`. @@ -106,6 +103,17 @@ class CodeTester(projects: List[Project]) { def references(range: CodeRange, expected: List[CodeRange], withDecl: Boolean = false): this.type = doAction(new CodeReferences(range, expected, withDecl)) + /** + * Requests completions at position `marker` with default value of `m1`, verifies that the results are empty + * `expected`. + * + * @param marker The position from which to ask for completions. + * + * @see dotty.tools.languageserver.util.actions.CodeCompletion + */ + def noCompletions(marker: CodeMarker = m1): this.type = + completion(marker, Set.empty) + /** * Requests completion at the position defined by `marker`, verifies that the results match * `expected`. @@ -118,6 +126,17 @@ class CodeTester(projects: List[Project]) { def completion(marker: CodeMarker, expected: Set[(String, CompletionItemKind, String)]): this.type = completion(marker, results => assertEquals(expected, CodeCompletion.simplifyResults(results))) + /** + * Requests completion at default position defined by `marker`, verifies that the results match `expected`. + * + * @param marker The position from which to ask for completions. + * @param expected The expected completion results. + * + * @see dotty.tools.languageserver.util.actions.CodeCompletion + */ + def completion(marker: CodeMarker, expected: (String, CompletionItemKind, String) *): this.type = + completion(marker, expected.toSet) + /** * Requests completion at the position defined by `marker`, and pass the results to * `checkResults`. @@ -130,6 +149,27 @@ class CodeTester(projects: List[Project]) { def completion(marker: CodeMarker, checkResults: Set[CompletionItem] => Unit): this.type = doAction(new CodeCompletion(marker, checkResults)) + /** + * Requests completion at default position defined by `m1`, verifies that the results match `expected`. + * + * @param expected The expected completion results. + * + * @see dotty.tools.languageserver.util.actions.CodeCompletion + */ + def completion(expected: (String, CompletionItemKind, String) *): this.type = + completion(m1, expected.toSet) + + /** + * Requests completion at default position defined by `m1`, and pass the results to + * `checkResults`. + * + * @param checkResults A function that verifies that the results of completion are correct. + * + * @see dotty.tools.languageserver.util.actions.CodeCompletion + */ + def completion(checkResults: Set[CompletionItem] => Unit): this.type = + doAction(new CodeCompletion(m1, checkResults)) + /** * Performs a workspace-wide renaming of the symbol under `marker`, verifies that the positions to * update match `expected`.