Skip to content

Commit

Permalink
Handle globs properly (ScalablyTyped#638)
Browse files Browse the repository at this point in the history
  • Loading branch information
steinybot committed Jul 29, 2024
1 parent b36868a commit cdf4316
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 151 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
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 (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 @@ -48,6 +48,12 @@ object LibTsSource {
def fromFileEntry(fromFolder: LibTsSource.FromFolder, files: Option[IArray[String]]): IArray[InFile] =
files.getOrElse(IArray.Empty).mapNotNone(file => LibraryResolver.file(fromFolder.folder, file))

def fromFilesGlobEntry(fromFolder: LibTsSource.FromFolder, globs: Option[IArray[String]]): IArray[InFile] = {
val baseDirectory = fromFolder.folder.path
val files = globs.fold(os.walk(baseDirectory))(GlobWalker.walkFiles(baseDirectory, _)).map(InFile(_))
IArray.fromTraversable(files)
}

def fromModuleDeclaration(
fromFolder: LibTsSource.FromFolder,
files: Option[Map[String, String]],
Expand Down Expand Up @@ -78,19 +84,9 @@ object LibTsSource {
if (fromTypings.nonEmpty) fromTypings
else fromModuleDeclaration(f, f.packageJsonOpt.flatMap(_.parsedModules))

// This used to only find files from the types and typings fields but that is far too limited.
// At the very least we need to also include any types specified in the files field.
// FIXME: The files field includes file patterns but this assumes that they are all files/folders pointing to
// modules.
val filesTypings = fromFileEntry(f, f.packageJsonOpt.flatMap(_.files))

val x = (mainTypings ++ filesTypings).distinct

println("shortenedFiles:")
println(x.mkString("\n"))
println
val filesTypings = fromFilesGlobEntry(f, f.packageJsonOpt.flatMap(_.files))

x
(mainTypings ++ filesTypings).distinct
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,11 @@ class Phase1ReadTypescript(
f.shortenedFiles
case f: LibTsSource.FromFolder =>
/* There are often whole trees parallel to what is specified in `typings` (or similar). This ignores some of them. */
val bound = f.shortenedFiles.map(_.folder)
val bound = f.shortenedFiles.map(_.folder).distinct
val boundOrParent = if (bound.isEmpty) IArray(f.folder) else bound
boundOrParent.flatMap(PathsFromTsLibSource.filesFrom).distinct
}

println("includedFiles:")
println(includedFiles.mkString("\n"))
println

val includedViaDirective = mutable.Set.empty[InFile]

lazy val preparingFiles: SortedMap[InFile, Lazy[(TsParsedFile, Set[LibTsSource])]] =
Expand Down
2 changes: 1 addition & 1 deletion tests/stripe/check-3/s/stripe-js/build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
organization := "org.scalablytyped"
name := "stripe-js"
version := "4.1.0-a4332d"
version := "4.1.0-e39ecd"
scalaVersion := "3.3.1"
enablePlugins(ScalaJSPlugin)
libraryDependencies ++= Seq(
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package typings.stripeJs

import typings.stripeJs.distStripeJsStripeMod.Stripe
import typings.stripeJs.distStripeJsStripeMod.StripeConstructor
import typings.stripeJs.distStripeJsStripeMod.StripeConstructorOptions
import typings.stripeJs.anon.SetLoadParameters
import org.scalablytyped.runtime.StObject
import scala.scalajs.js
import scala.scalajs.js.annotation.{JSGlobalScope, JSGlobal, JSImport, JSName, JSBracketAccess}
Expand All @@ -13,9 +11,98 @@ object mod {
@js.native
val ^ : js.Any = js.native

@JSImport("stripe-js", "loadStripe")
@js.native
val loadStripe: (/* import warning: importer.ImportType#apply Failed type conversion: typeof _loadStripe */ js.Any) & SetLoadParameters = js.native
inline def loadStripe(publishableKey: String): js.Promise[Stripe | Null] = ^.asInstanceOf[js.Dynamic].applyDynamic("loadStripe")(publishableKey.asInstanceOf[js.Any]).asInstanceOf[js.Promise[Stripe | Null]]
inline def loadStripe(publishableKey: String, options: StripeConstructorOptions): js.Promise[Stripe | Null] = (^.asInstanceOf[js.Dynamic].applyDynamic("loadStripe")(publishableKey.asInstanceOf[js.Any], options.asInstanceOf[js.Any])).asInstanceOf[js.Promise[Stripe | Null]]

trait Stripe extends StObject {

def foo(): Unit
}
object Stripe {

inline def apply(foo: () => Unit): Stripe = {
val __obj = js.Dynamic.literal(foo = js.Any.fromFunction0(foo))
__obj.asInstanceOf[Stripe]
}

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

inline def setFoo(value: () => Unit): Self = StObject.set(x, "foo", js.Any.fromFunction0(value))
}
}

type StripeConstructor = js.Function2[
/* publishableKey */ String,
/* options */ js.UndefOr[StripeConstructorOptions],
Stripe
]

trait StripeConstructorOptions extends StObject {

/**
* Override your account's [API version](https://stripe.com/docs/api/versioning).
*/
var apiVersion: js.UndefOr[String] = js.undefined

/**
* Opt-in to prerelease Stripe.js features by passing `betas` when instantiating a `Stripe` object.
*
* Supported values for the `betas` option can be found in integration guides for prerelease features.
* Most users of Stripe.js do not pass this option.
*/
var betas: js.UndefOr[js.Array[String]] = js.undefined

/**
* The [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag) used to globally configure localization in Stripe.js.
* Setting the locale here will localize error strings for all Stripe.js methods.
* It will also configure the locale for [Elements](#element_mount) and [Checkout](https://stripe.com/docs/js/checkout/redirect_to_checkout). Default is `auto` (Stripe detects the locale of the browser).
*
* Supported values depend on which features you are using.
* Checkout supports a slightly different set of locales than the rest of Stripe.js.
* If you are planning on using Checkout, make sure to use a [value](#checkout_redirect_to_checkout-options-locale) that it supports.
*/
var locale: js.UndefOr[String] = js.undefined

/**
* For usage with [Connect](https://stripe.com/docs/connect) only.
* Specifying a connected account ID (e.g., `acct_24BFMpJ1svR5A89k`) allows you to perform actions on behalf of that account.
*/
var stripeAccount: js.UndefOr[String] = js.undefined
}
object StripeConstructorOptions {

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

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

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

inline def setApiVersionUndefined: Self = StObject.set(x, "apiVersion", js.undefined)

inline def setBetas(value: js.Array[String]): Self = StObject.set(x, "betas", value.asInstanceOf[js.Any])

inline def setBetasUndefined: Self = StObject.set(x, "betas", js.undefined)

inline def setBetasVarargs(value: String*): Self = StObject.set(x, "betas", js.Array(value*))

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

inline def setLocaleUndefined: Self = StObject.set(x, "locale", js.undefined)

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

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

object global {

trait Window extends StObject {
Expand Down

0 comments on commit cdf4316

Please sign in to comment.