diff --git a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala index 3f3e5e25f66e..c181c340d66d 100644 --- a/compiler/src/dotty/tools/dotc/interactive/Interactive.scala +++ b/compiler/src/dotty/tools/dotc/interactive/Interactive.scala @@ -282,12 +282,10 @@ object Interactive { case nested :: encl :: rest => val outer = contextOfPath(encl :: rest) try encl match { - case tree @ PackageDef(pkg, stats) => - assert(tree.symbol.exists) + case tree @ PackageDef(pkg, stats) if tree.symbol.exists => if (nested `eq` pkg) outer else contextOfStat(stats, nested, pkg.symbol.moduleClass, outer.packageContext(tree, tree.symbol)) - case tree: DefDef => - assert(tree.symbol.exists) + case tree: DefDef if tree.symbol.exists => val localCtx = outer.localContext(tree, tree.symbol).setNewScope for params <- tree.paramss; param <- params do localCtx.enter(param.symbol) // Note: this overapproximates visibility a bit, since value parameters are only visible diff --git a/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala b/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala index d20537f0239e..231960ec5116 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/CompilerSearchVisitor.scala @@ -58,6 +58,7 @@ class CompilerSearchVisitor( .filter(denot => denot.exists) .map(_.symbol) .filter(isAccessible) + .filter(!_.is(Flags.Given)) } loop(next, tl) case Nil => owners diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala index a0cf6bafcf46..415bef2cff25 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala @@ -15,6 +15,7 @@ import dotty.tools.dotc.util.Spans import dotty.tools.pc.utils.MtagsEnrichments.* import org.eclipse.lsp4j as l +import scala.annotation.tailrec enum CompletionKind: case Empty, Scope, Members @@ -55,8 +56,10 @@ object CompletionPos: val prevIsDot = if start - 1 >= 0 then text.charAt(start - 1) == '.' else false val kind = - if query.nn.isEmpty() && !prevIsDot then CompletionKind.Empty - else if prevIsDot then CompletionKind.Members + if prevIsDot then CompletionKind.Members + else if isImportOrExportSelect(cursorPos, treePath) then + CompletionKind.Members + else if query.nn.isEmpty then CompletionKind.Empty else CompletionKind.Scope CompletionPos(kind, start, end, query.nn, cursorPos, uri) @@ -84,6 +87,21 @@ object CompletionPos: (i, tabIndented) end inferIndent + private def isImportOrExportSelect( + pos: SourcePosition, + path: List[Tree], + )(using Context): Boolean = + @tailrec + def loop(enclosing: List[Tree]): Boolean = + enclosing match + case head :: tl if !head.sourcePos.contains(pos) => loop(tl) + case (tree: (Import | Export)) :: _ => + tree.selectors.exists(_.imported.sourcePos.contains(pos)) + case _ => false + + loop(path) + + /** * Returns the start offset of the identifier starting as the given offset position. */ diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala index e507862a2561..20555bdf8ebe 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/Completions.scala @@ -72,8 +72,8 @@ class Completions( case _ :: (withcursor @ Select(fun, name)) :: (appl: GenericApply) :: _ if appl.fun == withcursor && name.decoded == Cursor.value => false - case (_: Import) :: _ => false - case _ :: (_: Import) :: _ => false + case (_: (Import | Export)) :: _ => false + case _ :: (_: (Import | Export)) :: _ => false case (_: Ident) :: (_: SeqLiteral) :: _ => false case _ => true @@ -140,7 +140,8 @@ class Completions( val application = CompletionApplication.fromPath(path) val ordering = completionOrdering(application) - val values = application.postProcess(all.sorted(ordering)) + val sorted = all.sorted(ordering) + val values = application.postProcess(sorted) (values, result) end completions @@ -441,6 +442,10 @@ class Completions( true, ) + case (tree: (Import | Export)) :: _ + if tree.selectors.exists(_.renamed.sourcePos.contains(pos)) => + (List.empty, true) + // From Scala 3.1.3-RC3 (as far as I know), path contains // `Literal(Constant(null))` on head for an incomplete program, in this case, just ignore the head. case Literal(Constant(null)) :: tl => @@ -791,7 +796,8 @@ class Completions( val fuzzyCache = mutable.Map.empty[CompletionValue, Int] def compareLocalSymbols(s1: Symbol, s2: Symbol): Int = - if s1.isLocal && s2.isLocal then + if s1.isLocal && s2.isLocal && s1.sourcePos.exists && s2.sourcePos.exists + then val firstIsAfter = s1.srcPos.isAfter(s2.srcPos) if firstIsAfter then -1 else 1 else 0 @@ -833,6 +839,16 @@ class Completions( priority(o1) - priority(o2) end compareInApplyParams + def prioritizeKeywords(o1: CompletionValue, o2: CompletionValue): Int = + def priority(v: CompletionValue): Int = + v match + case _: CompletionValue.CaseKeyword => 0 + case _: CompletionValue.NamedArg => 1 + case _: CompletionValue.Keyword => 2 + case _ => 3 + + priority(o1) - priority(o2) + end prioritizeKeywords /** * Some completion values should be shown first such as CaseKeyword and * NamedArg @@ -909,7 +925,10 @@ class Completions( case _ => val byApplyParams = compareInApplyParams(o1, o2) if byApplyParams != 0 then byApplyParams - else compareByRelevance(o1, o2) + else + val keywords = prioritizeKeywords(o1, o2) + if keywords != 0 then keywords + else compareByRelevance(o1, o2) end compare end Completions diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala index 1d063bc6d873..768f68a66300 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/InterpolatorCompletions.scala @@ -83,14 +83,13 @@ object InterpolatorCompletions: case _: Select => true case _ => false } => - val allLiterals = parent match - case SeqLiteral(elems, _) => - elems - case _ => Nil - expr.elems.zip(allLiterals.tail).collectFirst { - case (i: (Ident | Select), literal) if literal == lit => - i - } + parent match + case SeqLiteral(elems, _) if elems.size > 0 => + expr.elems.zip(elems.tail).collectFirst { + case (i: (Ident | Select), literal) if literal == lit => + i + } + case _ => None end interpolatorMemberArg /** diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala index e4ae4070edb9..d1f6b01f758e 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/NamedArgCompletions.scala @@ -17,6 +17,7 @@ import dotty.tools.dotc.core.Names.Name import dotty.tools.dotc.core.StdNames.* import dotty.tools.dotc.core.SymDenotations.NoDenotation import dotty.tools.dotc.core.Symbols +import dotty.tools.dotc.core.Symbols.defn import dotty.tools.dotc.core.Symbols.NoSymbol import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.core.Types.AndType @@ -309,15 +310,17 @@ object NamedArgCompletions: val completionSymbols = indexedContext.scopeSymbols def matchingTypesInScope(paramType: Type): List[String] = - completionSymbols - .collect { - case sym - if sym.info <:< paramType && sym.isTerm && !sym.info.isErroneous && !sym.info.isNullType && !sym.info.isNothingType && !sym - .is(Flags.Method) && !sym.is(Flags.Synthetic) => - sym.decodedName - } - .filter(name => name != "Nil" && name != "None") - .sorted + if paramType != defn.AnyType then + completionSymbols + .collect { + case sym + if sym.info <:< paramType && sym.isTerm && !sym.info.isErroneous && !sym.info.isNullType && !sym.info.isNothingType && !sym + .is(Flags.Method) && !sym.is(Flags.Synthetic) => + sym.decodedName + } + .filter(name => name != "Nil" && name != "None") + .sorted + else Nil def findDefaultValue(param: ParamSymbol): String = val matchingType = matchingTypesInScope(param.info) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala index 16d54cc124ca..61239b535e1c 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionArgSuite.scala @@ -1047,7 +1047,7 @@ class CompletionArgSuite extends BaseCompletionSuite: | bbb = 123, | aa@@ | ) - |} + |} |""".stripMargin, """|aaa = : Int |""".stripMargin, @@ -1063,7 +1063,7 @@ class CompletionArgSuite extends BaseCompletionSuite: | ccc = 123, | aa@@ | ) - |} + |} |""".stripMargin, """|aaa = : Int |""".stripMargin, @@ -1079,7 +1079,7 @@ class CompletionArgSuite extends BaseCompletionSuite: | ccc = 123, | aa@@ | ) - |} + |} |""".stripMargin, """|aaa = : Int |""".stripMargin, @@ -1105,4 +1105,18 @@ class CompletionArgSuite extends BaseCompletionSuite: """|str = : String | """.stripMargin, topLines = Some(1), + ) + + @Test def `comparison` = + check( + """package a + |object w { + | abstract class T(x: Int) { + | def met(x: Int): Unit = { + | println(x@@) + | } + | }} + |""".stripMargin, + """x: Int + |x = : Any""".stripMargin, ) \ No newline at end of file diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala index 583b138a255b..ec4fedf50f68 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionKeywordSuite.scala @@ -38,7 +38,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | // tr@@ |} |""".stripMargin, - "", + """|transient scala (commit: '') + |transparentTrait - scala.annotation (commit: '')""".stripMargin, includeCommitCharacter = true ) @@ -57,7 +58,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | **/ |} |""".stripMargin, - "", + """|transient scala (commit: '') + |transparentTrait - scala.annotation (commit: '')""".stripMargin, includeCommitCharacter = true ) @@ -151,6 +153,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: """|value: Int |val |var + |varargs(): varargs + |varargs - scala.annotation |""".stripMargin ) @@ -167,6 +171,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: |""".stripMargin, """|val |var + |varargs(): varargs + |varargs - scala.annotation |""".stripMargin ) @@ -181,9 +187,10 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | } |} |""".stripMargin, - """|given (commit: '') - |""".stripMargin, - includeCommitCharacter = true + """given (commit: '') + |""".stripMargin, + includeCommitCharacter = true, + topLines = Some(5) ) @Test def `val-arg` = @@ -198,8 +205,8 @@ class CompletionKeywordSuite extends BaseCompletionSuite: |} |""".stripMargin, """|value: Int - |""".stripMargin, - topLines = Some(1) + |varargs(): varargs + |varargs - scala.annotation""".stripMargin ) @Test def `val-trailing-space` = @@ -406,7 +413,13 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | protected de@@ |} """.stripMargin, - "def" + """|def + |deprecated scala + |deprecatedInheritance scala + |deprecatedName scala + |deprecatedOverriding scala + |""".stripMargin, + topLines = Some(5) ) @Test def `protected-val` = @@ -418,9 +431,10 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | protected va@@ |} """.stripMargin, - """val - |var - |""".stripMargin + """|val + |var + |varargs - scala.annotation + |""".stripMargin ) @Test def `topLevel` = @@ -458,8 +472,13 @@ class CompletionKeywordSuite extends BaseCompletionSuite: | def hello(u@@) |}""".stripMargin, """|using (commit: '') + |unsafeExceptions scala (commit: '') + |unchecked scala (commit: '') + |unsafe - scala.caps (commit: '') + |unsafeNulls - scala.runtime.stdLibPatches.language (commit: '') |""".stripMargin, - includeCommitCharacter = true + includeCommitCharacter = true, + topLines = Some(5) ) @Test def `not-using` = @@ -467,7 +486,12 @@ class CompletionKeywordSuite extends BaseCompletionSuite: """|object A{ | def hello(a: String, u@@) |}""".stripMargin, - "" + """|unsafeExceptions scala + |unchecked scala + |unsafe - scala.caps + |unsafeNulls - scala.runtime.stdLibPatches.language + |unused - scala.annotation """.stripMargin, + topLines = Some(5) ) @Test def `extends-class` = diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala index 6d2261bbfe66..619ba523de0a 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionPatternSuite.scala @@ -54,7 +54,10 @@ class CompletionPatternSuite extends BaseCompletionSuite: | case ma@@ | } |}""".stripMargin, - "" + """|main scala + |macros - scala.languageFeature.experimental + |macroImpl - scala.reflect.macros.internal + |""".stripMargin ) @Test def `bind2` = diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSnippetSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSnippetSuite.scala index 586b70d54006..46e0fe7b1976 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSnippetSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSnippetSuite.scala @@ -323,7 +323,8 @@ class CompletionSnippetSuite extends BaseCompletionSuite: |Widget($0) - (age: Int): Widget |Widget($0) - (name: String, age: Int): Widget |""".stripMargin, - includeDetail = true + includeDetail = true, + topLines = Some(4) ) @Test def `no-apply` = @@ -335,8 +336,13 @@ class CompletionSnippetSuite extends BaseCompletionSuite: | Wi@@ |} |""".stripMargin, - "Widget - example", - includeDetail = true + """|Widget - example + |Window - java.awt + |WindowPeer - java.awt.peer + |WithFilter - scala.collection + |""".stripMargin, + includeDetail = true, + topLines = Some(4) ) // https://github.com/scalameta/metals/issues/4004 diff --git a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala index 055363830a1b..5bc04e89c678 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala @@ -618,9 +618,6 @@ class CompletionSuite extends BaseCompletionSuite: """|Some(value) scala |Some scala |Some[A](value: A): Some[A] - |SomeToExpr(x: Some[T])(using Quotes): Expr[Some[T]] - |SomeToExpr[T: Type: ToExpr]: SomeToExpr[T] - |SomeFromExpr[T](using Type[T], FromExpr[T]): SomeFromExpr[T] |""".stripMargin ) @@ -633,9 +630,6 @@ class CompletionSuite extends BaseCompletionSuite: |""".stripMargin, """|Some scala |Some[A](value: A): Some[A] - |SomeToExpr(x: Some[T])(using Quotes): Expr[Some[T]] - |SomeToExpr[T: Type: ToExpr]: SomeToExpr[T] - |SomeFromExpr[T](using Type[T], FromExpr[T]): SomeFromExpr[T] |""".stripMargin ) @@ -1329,6 +1323,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (x: Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1349,6 +1353,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A <: Fo@@] |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1369,6 +1383,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (using Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1380,6 +1404,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (x: Int)(using Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1390,6 +1424,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (using Fo@@)(x: Int)(using Foo) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1400,6 +1444,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension (using Foo)(x: Int)(using Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1410,6 +1464,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A](x: Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1420,6 +1484,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A](using Fo@@)(x: Int) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1430,6 +1504,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A](using Foo)(x: Fo@@) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1440,6 +1524,16 @@ class CompletionSuite extends BaseCompletionSuite: | extension [A](using Foo)(x: Fo@@)(using Foo) |""".stripMargin, """|Foo test + |Font - java.awt + |Form - java.text.Normalizer + |Format - java.text + |FontPeer - java.awt.peer + |FormView - javax.swing.text.html + |Formatter - java.util + |Formatter - java.util.logging + |FocusEvent - java.awt.event + |FontMetrics - java.awt + |Found - scala.collection.Searching |""".stripMargin ) @@ -1545,3 +1639,43 @@ class CompletionSuite extends BaseCompletionSuite: assertSingleItem = false ) + + @Test def `multi-export` = + check( + """export scala.collection.{AbstractMap, Set@@} + |""".stripMargin, + """Set scala.collection + |SetOps scala.collection + |""".stripMargin + ) + + @Test def `multi-imports` = + check( + """import scala.collection.{AbstractMap, Set@@} + |""".stripMargin, + """Set scala.collection + |SetOps scala.collection + |""".stripMargin, + ) + + + @Test def `multi-imports-empty-query` = + check( + """import scala.collection.{AbstractMap, @@} + |""".stripMargin, + """GenIterable scala.collection + |GenMap scala.collection + |GenSeq scala.collection + |GenSet scala.collection + |GenTraversable scala.collection + |""".stripMargin, + topLines = Some(5) + ) + + + @Test def `import-rename` = + check( + """import scala.collection.{AbstractMap => Set@@} + |""".stripMargin, + "" + ) diff --git a/presentation-compiler/test/dotty/tools/pc/tests/highlight/DocumentHighlightSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/highlight/DocumentHighlightSuite.scala index 1dc2a7b156db..5d9893f6a1c1 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/highlight/DocumentHighlightSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/highlight/DocumentHighlightSuite.scala @@ -1186,7 +1186,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |""".stripMargin, ) - @Test def `constructor` = + @Test def `constructor` = check( """ |object Main { @@ -1195,7 +1195,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor1` = + @Test def `constructor1` = check( """ |object Main { @@ -1204,7 +1204,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor2` = + @Test def `constructor2` = check( """ |object Main { @@ -1214,7 +1214,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor3` = + @Test def `constructor3` = check( """ |object Main { @@ -1224,7 +1224,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor4` = + @Test def `constructor4` = check( """ |object Main { @@ -1234,7 +1234,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor5` = + @Test def `constructor5` = check( """ |object Main { @@ -1246,7 +1246,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor6` = + @Test def `constructor6` = check( """ |class <>[T](a: T) @@ -1256,7 +1256,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor7` = + @Test def `constructor7` = check( """ |object Bar { @@ -1268,7 +1268,7 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: |}""".stripMargin ) - @Test def `constructor8` = + @Test def `constructor8` = check( """ |object Bar { @@ -1279,3 +1279,188 @@ class DocumentHighlightSuite extends BaseDocumentHighlightSuite: | val x = Bar.<>[Int](2) |}""".stripMargin ) + + @Test def `i5630` = + check( + """|class MyIntOut(val value: Int) + |object MyIntOut: + | extension (i: MyIntOut) def <> = i.value % 2 == 1 + | + |val a = MyIntOut(1) + |val m = a.<> + |""".stripMargin + ) + + @Test def `i5630-2` = + check( + """|class MyIntOut(val value: Int) + |object MyIntOut: + | extension (i: MyIntOut) def <>(u: Int) = i.value % 2 == 1 + | + |val a = MyIntOut(1).<>(3) + |""".stripMargin + ) + + @Test def `i5630-infix` = + check( + """|class MyIntOut(val value: Int) + |object MyIntOut: + | extension (i: MyIntOut) def <<++>>(u: Int) = i.value + u + | + |val a = MyIntOut(1) <<+@@+>> 3 + |""".stripMargin + ) + + @Test def `i5921-1` = + check( + """|object Logarithms: + | opaque type Logarithm = Double + | extension [K](vmap: Logarithm) + | def <>(k: Logarithm): Logarithm = ??? + | + |object Test: + | val in: Logarithms.Logarithm = ??? + | in.<>(in) + |""".stripMargin + ) + + @Test def `i5921-2` = + check( + """|object Logarithms: + | opaque type Logarithm = Double + | extension [K](vmap: Logarithm) + | def <>(k: Logarithm): Logarithm = ??? + | + |object Test: + | val in: Logarithms.Logarithm = ??? + | in.<>(in) + |""".stripMargin + ) + + @Test def `i5921-3` = + check( + """|object Logarithms: + | opaque type Logarithm = Double + | extension [K](vmap: Logarithm) + | def <>(k: Logarithm): Logarithm = ??? + | (2.0).<>(1.0) + |""".stripMargin + ) + + @Test def `i5921-4` = + check( + """|object Logarithms: + | opaque type Logarithm = Double + | extension [K](vmap: Logarithm) + | def <>(k: Logarithm): Logarithm = ??? + | (2.0).<>(1.0) + |""".stripMargin + ) + + @Test def `i5977` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + @Test def `i5977-1` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + @Test def `i5977-2` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + @Test def `i5977-3` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + @Test def `i5977-4` = + check( + """ + |sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def <>[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Int](_.<>("str")) + | usage[Int](_.<>[String]("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>("str")) + | usage[Option[Int]](_.typeArg[Some[Int]].value.<>[String]("str")) + |} + |""".stripMargin + ) + + +end DocumentHighlightSuite diff --git a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala index 7ce81464fbd6..cf4682bd9a11 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/hover/HoverTermSuite.scala @@ -412,3 +412,185 @@ class HoverTermSuite extends BaseHoverSuite: |""".stripMargin, "def this(): tailrec".hover ) + + @Test def `i5630` = + check( + """class MyIntOut(val value: Int) + |object MyIntOut: + | extension (i: MyIntOut) def uneven = i.value % 2 == 1 + | + |val a = MyIntOut(1).un@@even + |""".stripMargin, + """extension (i: MyIntOut) def uneven: Boolean + |""".stripMargin.hover + ) + + @Test def `i5921` = + check( + """object Logarithms: + | trait Logarithm + | extension [K](vmap: Logarithm) + | def multiply(k: Logarithm): Logarithm = ??? + | + |object Test: + | val in: Logarithms.Logarithm = ??? + | in.multi@@ply(in) + |""".stripMargin, + "extension [K](vmap: Logarithm) def multiply(k: Logarithm): Logarithm".hover + ) + + @Test def `i5976` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def noTypeArg: A + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.typeArg[Some[Int]].value.noTyp@@eArg.typeArg[Int]) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |Int + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def noTypeArg: A + |``` + |""".stripMargin + ) + + @Test def `i5976-1` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def noTypeArg: A + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.type@@Arg[Some[Int]].value.noTypeArg.typeArg[Int]) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |Some[Int] + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def typeArg[B <: A]: B + |``` + |""".stripMargin + ) + + @Test def `i5977` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def inferredTypeArg[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.infer@@redTypeArg("str")) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |String + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def inferredTypeArg[C](value: C): C + |``` + |""".stripMargin + ) + + @Test def `i5977-1` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def inferredTypeArg[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.infer@@redTypeArg[String]("str")) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |String + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def inferredTypeArg[C](value: C): C + |``` + |""".stripMargin + ) + + @Test def `i5977-2` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def inferredTypeArg[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.typeArg[Some[Int]].value.infer@@redTypeArg("str")) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |String + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def inferredTypeArg[C](value: C): C + |``` + |""".stripMargin + ) + + @Test def `i5977-3` = + check( + """sealed trait ExtensionProvider { + | extension [A] (self: A) { + | def typeArg[B <: A]: B + | def inferredTypeArg[C](value: C): C + | } + |} + | + |object Repro { + | def usage[A](f: ExtensionProvider ?=> A => Any): Any = ??? + | + | usage[Option[Int]](_.typeArg[Some[Int]].value.infer@@redTypeArg[String]("str")) + |} + |""".stripMargin, + """**Expression type**: + |```scala + |String + |``` + |**Symbol signature**: + |```scala + |extension [A](self: A) def inferredTypeArg[C](value: C): C + |``` + |""".stripMargin + ) \ No newline at end of file diff --git a/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala b/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala index c8cfac044732..fd90a8dfaca0 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/tokens/SemanticTokensSuite.scala @@ -411,4 +411,24 @@ class SemanticTokensSuite extends BaseSemanticTokensSuite: | } | val <>/*variable,definition,readonly*/ = <>/*class*/(123, 456) |}""".stripMargin + ) + + @Test def `i5977` = + check( + """ + |sealed trait <>/*interface,abstract*/ { + | extension [<>/*typeParameter,definition,abstract*/] (<>/*parameter,declaration,readonly*/: <>/*typeParameter,abstract*/) { + | def <>/*method,declaration*/[<>/*typeParameter,definition,abstract*/]: <>/*typeParameter,abstract*/ + | def <>/*method,declaration*/[<>/*typeParameter,definition,abstract*/](<>/*parameter,declaration,readonly*/: <>/*typeParameter,abstract*/): <>/*typeParameter,abstract*/ + |} + | + |object <>/*class*/ { + | def <>/*method,definition*/[<>/*typeParameter,definition,abstract*/](<>/*parameter,declaration,readonly*/: <>/*interface,abstract*/ ?=> <>/*typeParameter,abstract*/ => <>/*class,abstract*/): <>/*class,abstract*/ = <>/*method*/ + | + | <>/*method*/[<>/*class,abstract*/](<<_>>/*parameter,readonly*/.<>/*method*/("str")) + | <>/*method*/[<>/*class,abstract*/](<<_>>/*parameter,readonly*/.<>/*method*/[<>/*type*/]("str")) + | <>/*method*/[<