Skip to content

Fix imports/exports from local sibling modules #639

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
  •  
  •  
  •  
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.scalablytyped.converter.internal.importer

import geny.Generator
import org.scalablytyped.converter.internal.IArray

import java.nio.file.FileSystems
import scala.util.Try

object GlobWalker {

/**
* Traverses the base directory and returns all files that match a given glob.
*
* Only returns files, not directories. If a directory matches a glob then all its descendents are included.
*
* @see the glob syntax in [[java.nio.file.FileSystem#getPathMatcher]]
*/
def walkFiles(baseDirectory: os.Path, globs: IArray[String]): IndexedSeq[os.Path] = {
val pathOrMatchers = globs.map { glob =>
Try(FileSystems.getDefault.getPathMatcher(s"glob:$glob")).toOption.toRight(baseDirectory / glob)
}

def matches(path: os.Path) = {
val relativePath = path.relativeTo(baseDirectory)
pathOrMatchers.exists {
case Left(invalidGlob) => invalidGlob.toString == relativePath.toString
case Right(matcher) => matcher.matches(relativePath.toNIO)
}
}

val builder = IndexedSeq.newBuilder[os.Path]

def processDirectoryAndSkip(dir: os.Path): Boolean =
if (dir.toIO.isDirectory && matches(dir)) {
os.walk.stream(dir).generate { path =>
if (path.toIO.isFile) builder += path
Generator.Continue
}
true
} else false

os.walk.stream(baseDirectory, processDirectoryAndSkip).generate { path =>
if (path.toIO.isFile && matches(path)) builder += path
Generator.Continue
}

builder.result()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package importer

import com.olvind.logging.{Formatter, Logger}
import org.scalablytyped.converter.Selection
import org.scalablytyped.converter.internal.importer.Phase1ReadTypescript.{packageJsonFiles, packageJsonMain}
import org.scalablytyped.converter.internal.maps._
import org.scalablytyped.converter.internal.phases.{GetDeps, IsCircular, Phase, PhaseRes}
import org.scalablytyped.converter.internal.ts.TsTreeScope.LoopDetector
Expand Down Expand Up @@ -56,9 +57,12 @@ class Phase1ReadTypescript(
/* don't include std */
f.shortenedFiles
case f: LibTsSource.FromFolder =>
/* There are often whole trees parallel to what is specified in `typings` (or similar). This ignores them */
val bound = f.shortenedFiles.headOption.map(_.folder).getOrElse(f.folder)
PathsFromTsLibSource.filesFrom(bound)
/* There are often whole trees parallel to what is specified in `typings` (or similar). This ignores some of them. */
val main = packageJsonMain(f)
val includedFiles = packageJsonFiles(f)
val bound =
(f.shortenedFiles ++ main ++ includedFiles).map(_.folder).distinct.filter(_.path.toIO.exists())
bound.flatMap(PathsFromTsLibSource.filesFrom).distinct
}

val includedViaDirective = mutable.Set.empty[InFile]
Expand Down Expand Up @@ -341,4 +345,17 @@ object Phase1ReadTypescript {
T.VarToNamespace // after ExtractClasses
).visitTsParsedFile(scope.caching),
)

private def packageJsonMain(fromFolder: LibTsSource.FromFolder): IArray[InFile] = {
val baseDirectory = fromFolder.folder.path
val main = os.RelPath(fromFolder.packageJsonOpt.flatMap(_.main).getOrElse("index.js"))
IArray(InFile(baseDirectory / main))
}

private def packageJsonFiles(fromFolder: LibTsSource.FromFolder): IArray[InFile] = {
val baseDirectory = fromFolder.folder.path
val globs = fromFolder.packageJsonOpt.flatMap(_.files)
val files = globs.fold(os.walk(baseDirectory))(GlobWalker.walkFiles(baseDirectory, _)).map(InFile(_))
IArray.fromTraversable(files)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ trait ImporterTest extends AnyFunSuite with ImporterHarness with ParallelTestExe
test("recharts")(assertImportsOk("recharts", pedantic = true))
test("firebase")(assertImportsOk("firebase", pedantic = true))
test("prisma")(assertImportsOk("prisma", pedantic = true))
test("stripe")(assertImportsOk("stripe", pedantic = true))
test("zootools")(assertImportsOk("zootools", pedantic = true))

test("material-ui-slinky")(
assertImportsOk("material-ui", pedantic = true, flavour = Slinky),
Expand Down
6 changes: 4 additions & 2 deletions tests/antd/check-3/a/antd/build.sbt
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
organization := "org.scalablytyped"
name := "antd"
version := "4.3.1-87f21b"
version := "4.3.1-105798"
scalaVersion := "3.3.1"
enablePlugins(ScalaJSPlugin)
libraryDependencies ++= Seq(
"com.olvind" %%% "scalablytyped-runtime" % "2.4.2")
"com.olvind" %%% "scalablytyped-runtime" % "2.4.2",
"org.scalablytyped" %%% "react" % "0.0-unknown-71761d",
"org.scalablytyped" %%% "std" % "0.0-unknown-be9d8f")
publishArtifact in packageDoc := false
scalacOptions ++= List("-encoding", "utf-8", "-feature", "-language:implicitConversions", "-language:higherKinds", "-language:existentials", "-no-indent", "-source:future")
licenses += ("MIT", url("http://opensource.org/licenses/MIT"))
64 changes: 64 additions & 0 deletions tests/antd/check-3/a/antd/src/main/scala/typings/antd/anon.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package typings.antd

import org.scalablytyped.runtime.StObject
import scala.scalajs.js
import scala.scalajs.js.annotation.{JSGlobalScope, JSGlobal, JSImport, JSName, JSBracketAccess}

object anon {

trait Delay extends StObject {

var delay: js.UndefOr[Double] = js.undefined
}
object Delay {

inline def apply(): Delay = {
val __obj = js.Dynamic.literal()
__obj.asInstanceOf[Delay]
}

@scala.inline
implicit open class MutableBuilder[Self <: Delay] (val x: Self) extends AnyVal {

inline def setDelay(value: Double): Self = StObject.set(x, "delay", value.asInstanceOf[js.Any])

inline def setDelayUndefined: Self = StObject.set(x, "delay", js.undefined)
}
}

trait Icon extends StObject {

var icon: String
}
object Icon {

inline def apply(icon: String): Icon = {
val __obj = js.Dynamic.literal(icon = icon.asInstanceOf[js.Any])
__obj.asInstanceOf[Icon]
}

@scala.inline
implicit open class MutableBuilder[Self <: Icon] (val x: Self) extends AnyVal {

inline def setIcon(value: String): Self = StObject.set(x, "icon", value.asInstanceOf[js.Any])
}
}

trait IconAny extends StObject {

var icon: Any
}
object IconAny {

inline def apply(icon: Any): IconAny = {
val __obj = js.Dynamic.literal(icon = icon.asInstanceOf[js.Any])
__obj.asInstanceOf[IconAny]
}

@scala.inline
implicit open class MutableBuilder[Self <: IconAny] (val x: Self) extends AnyVal {

inline def setIcon(value: Any): Self = StObject.set(x, "icon", value.asInstanceOf[js.Any])
}
}
}
Loading
Loading