From adadc1129798b8cf33cf74af5a51d8f9c858f1bc Mon Sep 17 00:00:00 2001 From: Vadim Chelyshov Date: Mon, 24 Oct 2022 15:38:22 +0300 Subject: [PATCH] fix: add special case for autoimport inside Import tree (#4555) fix: add special case for autoimport inside `Import` tree Previously, the behaviour for auto-import action wasn't specified for `import <<$SYMBOL>>` case. Now in imports the required symbol using specifying full name in case if it's missing in scope as we do that in completions --- .../internal/pc/AutoImportsProvider.scala | 24 ++++++++++----- .../internal/pc/AutoImportsProvider.scala | 30 +++++++++++++------ .../scala/tests/pc/AutoImportsSuite.scala | 16 ++++++++++ 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/mtags/src/main/scala-2/scala/meta/internal/pc/AutoImportsProvider.scala b/mtags/src/main/scala-2/scala/meta/internal/pc/AutoImportsProvider.scala index 42a1b1b49f4..6254cef71ba 100644 --- a/mtags/src/main/scala-2/scala/meta/internal/pc/AutoImportsProvider.scala +++ b/mtags/src/main/scala-2/scala/meta/internal/pc/AutoImportsProvider.scala @@ -6,7 +6,7 @@ import scala.meta.internal.jdk.CollectionConverters._ import scala.meta.pc.AutoImportsResult import scala.meta.pc.OffsetParams -import org.eclipse.lsp4j.TextEdit +import org.eclipse.{lsp4j => l} final class AutoImportsProvider( val compiler: MetalsGlobal, @@ -44,6 +44,17 @@ final class AutoImportsProvider( search.search(name, buildTargetIdentifier, visitor) + def isInImportTree: Boolean = lastVisitedParentTrees match { + case (_: Import) :: _ => true + case _ => false + } + + def namePos: l.Range = + pos + .withStart(pos.start - name.length()) + .withEnd(pos.end) + .toLsp + def isExactMatch(sym: Symbol, name: String): Boolean = sym.name.dropLocal.decoded == name @@ -51,6 +62,10 @@ final class AutoImportsProvider( case sym if isExactMatch(sym, name) => val pkg = sym.owner.fullName val edits = importPosition match { + // if we are in import section just specify full name + case None if isInImportTree => + val nameEdit = new l.TextEdit(namePos, sym.fullNameSyntax) + List(nameEdit) case None => // No import position means we can't insert an import without clashing with // existing symbols in scope, so we just do nothing @@ -62,12 +77,7 @@ final class AutoImportsProvider( context, value ) - val namePos = - pos - .withStart(pos.start - name.length()) - .withEnd(pos.end) - .toLsp - val nameEdit = new TextEdit(namePos, short) + val nameEdit = new l.TextEdit(namePos, short) nameEdit :: edits } AutoImportsResultImpl(pkg, edits.asJava) diff --git a/mtags/src/main/scala-3/scala/meta/internal/pc/AutoImportsProvider.scala b/mtags/src/main/scala-3/scala/meta/internal/pc/AutoImportsProvider.scala index bbc795417b0..6a0ac25774b 100644 --- a/mtags/src/main/scala-3/scala/meta/internal/pc/AutoImportsProvider.scala +++ b/mtags/src/main/scala-3/scala/meta/internal/pc/AutoImportsProvider.scala @@ -74,18 +74,30 @@ final class AutoImportsProvider( if results.nonEmpty then val correctedPos = CompletionPos.infer(pos, params, path).sourcePos - val generator = - AutoImports.generator( - correctedPos, - params.text, - tree, - indexedContext.importContext, - config, - ) + val mkEdit = + path match + // if we are in import section just specify full name + case (_: Ident) :: (_: Import) :: _ => + (sym: Symbol) => + val nameEdit = + new l.TextEdit(correctedPos.toLsp, sym.fullNameBackticked) + Some(List(nameEdit)) + case _ => + val generator = + AutoImports.generator( + correctedPos, + params.text, + tree, + indexedContext.importContext, + config, + ) + (sym: Symbol) => generator.forSymbol(sym) + end match + end mkEdit for sym <- results - edits <- generator.forSymbol(sym) + edits <- mkEdit(sym) yield AutoImportsResultImpl( sym.owner.showFullName, edits.asJava, diff --git a/tests/cross/src/test/scala/tests/pc/AutoImportsSuite.scala b/tests/cross/src/test/scala/tests/pc/AutoImportsSuite.scala index 67ffa1c5e12..b9754fcf416 100644 --- a/tests/cross/src/test/scala/tests/pc/AutoImportsSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/AutoImportsSuite.scala @@ -281,6 +281,22 @@ class AutoImportsSuite extends BaseAutoImportsSuite { |""".stripMargin, ) + checkEdit( + "import-in-import", + """|package inimport + | + |object A { + | import <>.global + |} + |""".stripMargin, + """|package inimport + | + |object A { + | import scala.concurrent.ExecutionContext.global + |} + |""".stripMargin, + ) + checkAmmoniteEdit( "first-auto-import-amm-script", ammoniteWrapper(