diff --git a/core/src/main/scala/org/scalablytyped/converter/internal/IArray.scala b/core/src/main/scala/org/scalablytyped/converter/internal/IArray.scala index 0dc9f4c569..27df28ec8a 100644 --- a/core/src/main/scala/org/scalablytyped/converter/internal/IArray.scala +++ b/core/src/main/scala/org/scalablytyped/converter/internal/IArray.scala @@ -763,6 +763,7 @@ final class IArray[+A <: AnyRef](private val array: Array[AnyRef], val length: I } def drop(n: Int): IArray[A] = { + if (n == 0) return this val newLength = math.max(0, length - n) if (newLength == 0) return IArray.Empty val ret = Array.ofDim[AnyRef](newLength) diff --git a/core/src/main/scala/org/scalablytyped/converter/internal/scalajs/QualifiedName.scala b/core/src/main/scala/org/scalablytyped/converter/internal/scalajs/QualifiedName.scala index 06407846a9..5c80fd1e3c 100644 --- a/core/src/main/scala/org/scalablytyped/converter/internal/scalajs/QualifiedName.scala +++ b/core/src/main/scala/org/scalablytyped/converter/internal/scalajs/QualifiedName.scala @@ -3,7 +3,8 @@ package scalajs import io.circe013.{Decoder, Encoder} import io.circe013.generic.semiauto.{deriveDecoder, deriveEncoder} -import org.scalablytyped.converter.internal.scalajs.QualifiedName.dropRoot +import org.scalablytyped.converter.internal.scalajs.QualifiedName.dropRootPart +import scala.annotation.tailrec final case class QualifiedName(parts: IArray[Name]) { def +(name: Name) = @@ -15,12 +16,18 @@ final case class QualifiedName(parts: IArray[Name]) { def startsWith(other: QualifiedName): Boolean = parts.startsWith(other.parts) - override lazy val hashCode = dropRoot(parts).hashCode + def dropRoot: QualifiedName = { + val partsWithoutRoot = dropRootPart(parts) + if (partsWithoutRoot eq parts) this + else QualifiedName(partsWithoutRoot) + } + + override lazy val hashCode = dropRootPart(parts).hashCode override def equals(obj: Any): Boolean = obj match { case other: QualifiedName if other.hashCode == hashCode => - dropRoot(parts) === dropRoot(other.parts) + dropRootPart(parts) === dropRootPart(other.parts) case _ => false } } @@ -118,6 +125,9 @@ object QualifiedName { implicit val encodes: Encoder[QualifiedName] = deriveEncoder implicit val decodes: Decoder[QualifiedName] = deriveDecoder - private def dropRoot(parts: IArray[Name]): IArray[Name] = - parts.dropWhile(_ == Name.root) + @tailrec + private def dropRootPart(parts: IArray[Name]): IArray[Name] = + if (parts.isEmpty) parts + else if (parts(0) == Name.root) dropRootPart(parts.tail) + else parts } diff --git a/importer-portable/src/main/scala/org/scalablytyped/converter/internal/importer/AdaptiveNamingImport.scala b/importer-portable/src/main/scala/org/scalablytyped/converter/internal/importer/AdaptiveNamingImport.scala index 1328535eea..e04ab94d17 100644 --- a/importer-portable/src/main/scala/org/scalablytyped/converter/internal/importer/AdaptiveNamingImport.scala +++ b/importer-portable/src/main/scala/org/scalablytyped/converter/internal/importer/AdaptiveNamingImport.scala @@ -52,7 +52,7 @@ object AdaptiveNamingImport { // very obviously a hack. node is the only library seen so far where the shortest module name (`assert`) // doesnt correspond to the library name if (libraryName.value === "node") { - lowercaseIndex(s"_root_.${outputPkg.unescaped.toLowerCase}.node.mod") = IArray(TsIdentSimple("_____")) + lowercaseIndex(s"${outputPkg.unescaped.toLowerCase}.node.mod") = IArray(TsIdentSimple("_____")) } val illegalNames = (cleanIllegalNames.Illegal ++ ScalaJsClasses.jsObjectMembersByName.keys).map(_.value) diff --git a/scalajs/src/main/scala/org/scalablytyped/converter/internal/scalajs/Printer.scala b/scalajs/src/main/scala/org/scalablytyped/converter/internal/scalajs/Printer.scala index 188deee929..9997ee68b4 100644 --- a/scalajs/src/main/scala/org/scalablytyped/converter/internal/scalajs/Printer.scala +++ b/scalajs/src/main/scala/org/scalablytyped/converter/internal/scalajs/Printer.scala @@ -128,7 +128,7 @@ object Printer { case (ScalaOutput.File(name), members: IArray[Tree]) => reg.write(targetFolder / os.RelPath(s"${name.unescaped}.scala")) { writer => val (imports, shortenedMembers) = ShortenNames(tree, scope, parentsResolver)(members) - writer.println(s"package ${formatQN(QualifiedName(packages))}") + writer.println(s"package ${formatQN(QualifiedName(packages).dropRoot)}") writer.println("") imports.foreach(i => writer.println(s"import ${formatQN(i.imported)}")) writer.println(Imports) @@ -155,7 +155,7 @@ object Printer { reg.write(targetFolder / packageScalaFileName) { writer => val (imports, shortenedMembers) = ShortenNames(tree, scope, parentsResolver)(members) - writer.println(s"package ${formatQN(QualifiedName(packages))}") + writer.println(s"package ${formatQN(QualifiedName(packages).dropRoot)}") writer.println("") imports.foreach(i => writer.println(s"import ${formatQN(i.imported)}")) writer.println(Imports) @@ -177,7 +177,7 @@ object Printer { packages.dropRight(1) match { case IArray.Empty => () case remaining => - writer.println(s"package ${formatQN(QualifiedName(remaining))}") + writer.println(s"package ${formatQN(QualifiedName(remaining).dropRoot)}") } writer.println("") @@ -489,7 +489,7 @@ object Printer { else q.parts.map(formatName).mkString(".") def formatName(name: Name): String = name match { - case `outputPackage` => s"_root_.${outputPackage.unescaped}" // this let's dots in chosen package name slip through + case `outputPackage` => outputPackage.unescaped // this let's dots in chosen package name slip through case Name.APPLY => "apply" case Name.THIS => "this" case Name.SUPER => "super" diff --git a/scalajs/src/main/scala/org/scalablytyped/converter/internal/scalajs/TreeScope.scala b/scalajs/src/main/scala/org/scalablytyped/converter/internal/scalajs/TreeScope.scala index 5b53ff3bd1..6cabf37891 100644 --- a/scalajs/src/main/scala/org/scalablytyped/converter/internal/scalajs/TreeScope.scala +++ b/scalajs/src/main/scala/org/scalablytyped/converter/internal/scalajs/TreeScope.scala @@ -108,11 +108,13 @@ object TreeScope { override def _lookup(fragments: IArray[Name]): IArray[(Tree, TreeScope)] = fragments match { - case IArray.headHeadTail(`outputPkg`, head, tail) => + case IArray.headHeadTail(`outputPkg`, head, _) => dependencies.get(head) match { - case Some(dep) => dep.lookupNoBacktrack(outputPkg +: head +: tail) + case Some(dep) => dep.lookupNoBacktrack(fragments) case None => Empty } + case IArray.headTail(Name.root, tail) => + _lookup(tail) case _ => Empty } @@ -151,6 +153,9 @@ object TreeScope { def lookupNoBacktrack(names: IArray[Name]): IArray[(Tree, TreeScope)] = names match { + case IArray.headTail(Name.root, tail) => + lookupNoBacktrack(tail) + case IArray.exactlyOne(current.name) => IArray((current, this))