From 405a635e60a9efe871ee1a7be01cd8ec2ae2b80e Mon Sep 17 00:00:00 2001 From: rochala Date: Tue, 31 Oct 2023 15:26:33 +0100 Subject: [PATCH 1/2] Completions should prepend, not replace as it is for Scala 2 --- .../tools/pc/completions/CompletionPos.scala | 5 ++- .../pc/completions/CompletionProvider.scala | 29 ++++++++-------- .../pc/tests/completion/CompletionSuite.scala | 33 +++++++++++++++++++ 3 files changed, 48 insertions(+), 19 deletions(-) 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 9ce7939c10fa..29699bd05203 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionPos.scala @@ -29,10 +29,9 @@ case class CompletionPos( ): def sourcePos: SourcePosition = cursorPos.withSpan(Spans.Span(start, end)) + def stripSuffixEditRange: l.Range = new l.Range(cursorPos.offsetToPos(start), cursorPos.offsetToPos(end)) + def toEditRange: l.Range = cursorPos.withStart(start).withEnd(cursorPos.point).toLsp - def toEditRange: l.Range = - new l.Range(cursorPos.offsetToPos(start), cursorPos.offsetToPos(end)) - end toEditRange end CompletionPos object CompletionPos: diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala index 78f4affe8c49..01cd7264063c 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala @@ -151,10 +151,7 @@ class CompletionProvider( indexedContext: IndexedContext )(using ctx: Context): CompletionItem = val printer = - ShortenedTypePrinter(search, IncludeDefaultParam.ResolveLater)(using - indexedContext - ) - val editRange = completionPos.toEditRange + ShortenedTypePrinter(search, IncludeDefaultParam.ResolveLater)(using indexedContext) // For overloaded signatures we get multiple symbols, so we need // to recalculate the description @@ -165,24 +162,24 @@ class CompletionProvider( val ident = completion.insertText.getOrElse(completion.label) def mkItem( - insertText: String, + newText: String, additionalEdits: List[TextEdit] = Nil, range: Option[LspRange] = None ): CompletionItem = - val nameEdit = new TextEdit( - range.getOrElse(editRange), - insertText - ) + val oldText = params.text.substring(completionPos.start, completionPos.end) + val editRange = if newText.startsWith(oldText) then completionPos.stripSuffixEditRange + else completionPos.toEditRange + + val textEdit = range + .map(lspRange => new TextEdit(lspRange, newText)) + .getOrElse(new TextEdit(editRange, newText)) + val item = new CompletionItem(label) item.setSortText(f"${idx}%05d") item.setDetail(description) - item.setFilterText( - completion.filterText.getOrElse(completion.label) - ) - item.setTextEdit(nameEdit) - item.setAdditionalTextEdits( - (completion.additionalEdits ++ additionalEdits).asJava - ) + item.setFilterText(completion.filterText.getOrElse(completion.label)) + item.setTextEdit(textEdit) + item.setAdditionalTextEdits((completion.additionalEdits ++ additionalEdits).asJava) completion.insertMode.foreach(item.setInsertTextMode) completion 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 213dd7157293..a5101e4661b9 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala @@ -1500,3 +1500,36 @@ class CompletionSuite extends BaseCompletionSuite: |""".stripMargin, ) + @Test def `prepend-instead-of-replace` = + checkEdit( + """|object O: + | printl@@println() + |""".stripMargin, + """|object O: + | printlnprintln() + |""".stripMargin, + assertSingleItem = false + ) + + @Test def `prepend-instead-of-replace-duplicate-word` = + checkEdit( + """|object O: + | println@@println() + |""".stripMargin, + """|object O: + | printlnprintln() + |""".stripMargin, + assertSingleItem = false + ) + + @Test def `prepend-instead-of-replace-exact-same` = + checkEdit( + """|object O: + | println@@() + |""".stripMargin, + """|object O: + | println() + |""".stripMargin, + assertSingleItem = false + ) + From aee8e1ef23b1b8f654a1555add0f1f587d9248b6 Mon Sep 17 00:00:00 2001 From: rochala Date: Thu, 2 Nov 2023 10:51:58 +0100 Subject: [PATCH 2/2] Add test, refactor text edit creation --- .../tools/pc/completions/CompletionProvider.scala | 4 +--- .../tools/pc/tests/completion/CompletionSuite.scala | 13 ++++++++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala index 01cd7264063c..323f63050377 100644 --- a/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala +++ b/presentation-compiler/src/main/dotty/tools/pc/completions/CompletionProvider.scala @@ -170,9 +170,7 @@ class CompletionProvider( val editRange = if newText.startsWith(oldText) then completionPos.stripSuffixEditRange else completionPos.toEditRange - val textEdit = range - .map(lspRange => new TextEdit(lspRange, newText)) - .getOrElse(new TextEdit(editRange, newText)) + val textEdit = new TextEdit(range.getOrElse(editRange), newText) val item = new CompletionItem(label) item.setSortText(f"${idx}%05d") 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 a5101e4661b9..a64a6dfac6a2 100644 --- a/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala +++ b/presentation-compiler/test/dotty/tools/pc/tests/completion/CompletionSuite.scala @@ -1522,7 +1522,18 @@ class CompletionSuite extends BaseCompletionSuite: assertSingleItem = false ) - @Test def `prepend-instead-of-replace-exact-same` = + @Test def `replace-when-inside` = + checkEdit( + """|object O: + | print@@ln() + |""".stripMargin, + """|object O: + | println() + |""".stripMargin, + assertSingleItem = false + ) + + @Test def `replace-exact-same` = checkEdit( """|object O: | println@@()