-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Stabilise returned completions by improving deduplication + extra com…
…pletions for constructors (#19976) This PR doesn't address all issues. In the future we need to get rid of https://github.com/scala/scala3/compare/main...rochala:improved-deduplication-and-constructors-search?expand=1#diff-035851592480495dfdb20da6b615ec7dd77b3db70cda46aba56230d8cd690773R157-R167 as it is not working as intended. The future PR of shortened type printer refactor includes a proper way to split extension params. `CompletionValue.Interpolator` should also be removed, and instead we should return workspace / completions as it is now hard to sort those completions. Next refactor is reusing completion affix for other kinds of completions such as case completions, so prefix / suffix is handled in single place. This PR will unblock fuzzy search in the compiler because of stabilizing returned completions. [Cherry-picked 97313ed][modified]
- Loading branch information
1 parent
cb761cb
commit 7f28de1
Showing
23 changed files
with
1,252 additions
and
524 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
presentation-compiler/src/main/dotty/tools/pc/completions/CompletionAffix.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package dotty.tools.pc.completions | ||
|
||
import org.eclipse.lsp4j.Position | ||
import org.eclipse.lsp4j.Range | ||
|
||
/** | ||
* @param suffixes which we should insert | ||
* @param prefixes which we should insert | ||
* @param snippet which suffix should we insert the snippet $0 | ||
*/ | ||
case class CompletionAffix( | ||
suffixes: Set[Suffix], | ||
prefixes: Set[Prefix], | ||
snippet: Suffix, | ||
currentPrefix: Option[String], | ||
): | ||
def addLabelSnippet = suffixes.exists(_.kind == SuffixKind.Bracket) | ||
def hasSnippet = snippet.kind != SuffixKind.NoSuffix | ||
def chain(copyFn: CompletionAffix => CompletionAffix) = copyFn(this) | ||
def withNewSuffix(kind: Suffix) = this.copy(suffixes = suffixes + kind) | ||
def withNewPrefix(kind: Prefix) = this.copy(prefixes = prefixes + kind) | ||
def withCurrentPrefix(currentPrefix: String) = this.copy(currentPrefix = Some(currentPrefix)) | ||
def withNewSuffixSnippet(suffix: Suffix) = | ||
this.copy(suffixes = suffixes + suffix, snippet = suffix) | ||
|
||
def nonEmpty: Boolean = suffixes.nonEmpty || prefixes.nonEmpty | ||
|
||
def toSuffix: String = | ||
def loop(suffixes: List[SuffixKind]): String = | ||
def cursor = if suffixes.head == snippet.kind then "$0" else "" | ||
suffixes match | ||
case SuffixKind.Brace :: tail => s"($cursor)" + loop(tail) | ||
case SuffixKind.Bracket :: tail => s"[$cursor]" + loop(tail) | ||
case SuffixKind.Template :: tail => s" {$cursor}" + loop(tail) | ||
case _ => "" | ||
loop(suffixes.toList.map(_.kind)) | ||
|
||
def toSuffixOpt: Option[String] = | ||
val edit = toSuffix | ||
if edit.nonEmpty then Some(edit) else None | ||
|
||
|
||
given Ordering[Position] = Ordering.by(elem => (elem.getLine, elem.getCharacter)) | ||
|
||
def toInsertRange: Option[Range] = | ||
import scala.language.unsafeNulls | ||
|
||
val ranges = prefixes.collect: | ||
case Affix(_, Some(range)) => range | ||
.toList | ||
for | ||
startPos <- ranges.map(_.getStart).minOption | ||
endPos <- ranges.map(_.getEnd).maxOption | ||
yield Range(startPos, endPos) | ||
|
||
private def loopPrefix(prefixes: List[PrefixKind]): String = | ||
prefixes match | ||
case PrefixKind.New :: tail => "new " + loopPrefix(tail) | ||
case _ => "" | ||
|
||
/** | ||
* We need to insert previous prefix, but we don't want to display it in the label i.e. | ||
* ```scala | ||
* scala.util.Tr@@ | ||
* ```` | ||
* should return `new Try[T]: Try[T]` | ||
* but insert `new scala.util.Try` | ||
* | ||
*/ | ||
def toInsertPrefix: String = | ||
loopPrefix(prefixes.toList.map(_.kind)) + currentPrefix.getOrElse("") | ||
|
||
def toPrefix: String = | ||
loopPrefix(prefixes.toList.map(_.kind)) | ||
|
||
end CompletionAffix | ||
|
||
object CompletionAffix: | ||
val empty = CompletionAffix( | ||
suffixes = Set.empty, | ||
prefixes = Set.empty, | ||
snippet = Affix(SuffixKind.NoSuffix), | ||
currentPrefix = None, | ||
) | ||
|
||
enum SuffixKind: | ||
case Brace, Bracket, Template, NoSuffix | ||
|
||
enum PrefixKind: | ||
case New | ||
|
||
type Suffix = Affix[SuffixKind] | ||
type Prefix = Affix[PrefixKind] | ||
|
||
private case class Affix[+T](kind: T, insertRange: Option[Range] = None) |
Oops, something went wrong.