vendor tsgo
This commit is contained in:
134
tools/tsgo/internal/tsoptions/wildcarddirectories.go
Normal file
134
tools/tsgo/internal/tsoptions/wildcarddirectories.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package tsoptions
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/microsoft/typescript-go/internal/tspath"
|
||||
"github.com/microsoft/typescript-go/internal/vfs/vfsmatch"
|
||||
)
|
||||
|
||||
func getWildcardDirectories(include []string, exclude []string, comparePathsOptions tspath.ComparePathsOptions) map[string]bool {
|
||||
// We watch a directory recursively if it contains a wildcard anywhere in a directory segment
|
||||
// of the pattern:
|
||||
//
|
||||
// /a/b/**/d - Watch /a/b recursively to catch changes to any d in any subfolder recursively
|
||||
// /a/b/*/d - Watch /a/b recursively to catch any d in any immediate subfolder, even if a new subfolder is added
|
||||
// /a/b - Watch /a/b recursively to catch changes to anything in any recursive subfoler
|
||||
//
|
||||
// We watch a directory without recursion if it contains a wildcard in the file segment of
|
||||
// the pattern:
|
||||
//
|
||||
// /a/b/* - Watch /a/b directly to catch any new file
|
||||
// /a/b/a?z - Watch /a/b directly to catch any new file matching a?z
|
||||
|
||||
if len(include) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
excludeMatcher := vfsmatch.NewSpecMatcher(exclude, comparePathsOptions.CurrentDirectory, vfsmatch.UsageExclude, comparePathsOptions.UseCaseSensitiveFileNames)
|
||||
|
||||
wildcardDirectories := make(map[string]bool)
|
||||
wildCardKeyToPath := make(map[string]string)
|
||||
|
||||
var recursiveKeys []string
|
||||
|
||||
for _, file := range include {
|
||||
spec := tspath.NormalizePath(tspath.CombinePaths(comparePathsOptions.CurrentDirectory, file))
|
||||
if excludeMatcher != nil && excludeMatcher.MatchString(spec) {
|
||||
continue
|
||||
}
|
||||
|
||||
match := getWildcardDirectoryFromSpec(spec, comparePathsOptions.UseCaseSensitiveFileNames)
|
||||
if match != nil {
|
||||
key := match.Key
|
||||
path := match.Path
|
||||
recursive := match.Recursive
|
||||
|
||||
existingPath, existsPath := wildCardKeyToPath[key]
|
||||
var existingRecursive bool
|
||||
|
||||
if existsPath {
|
||||
existingRecursive = wildcardDirectories[existingPath]
|
||||
}
|
||||
|
||||
if !existsPath || (!existingRecursive && recursive) {
|
||||
pathToUse := path
|
||||
if existsPath {
|
||||
pathToUse = existingPath
|
||||
}
|
||||
wildcardDirectories[pathToUse] = recursive
|
||||
|
||||
if !existsPath {
|
||||
wildCardKeyToPath[key] = path
|
||||
}
|
||||
|
||||
if recursive {
|
||||
recursiveKeys = append(recursiveKeys, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any subpaths under an existing recursively watched directory
|
||||
for path := range wildcardDirectories {
|
||||
for _, recursiveKey := range recursiveKeys {
|
||||
key := toCanonicalKey(path, comparePathsOptions.UseCaseSensitiveFileNames)
|
||||
if key != recursiveKey && tspath.ContainsPath(recursiveKey, key, comparePathsOptions) {
|
||||
delete(wildcardDirectories, path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wildcardDirectories
|
||||
}
|
||||
|
||||
func toCanonicalKey(path string, useCaseSensitiveFileNames bool) string {
|
||||
if useCaseSensitiveFileNames {
|
||||
return path
|
||||
}
|
||||
return strings.ToLower(path)
|
||||
}
|
||||
|
||||
// wildcardDirectoryMatch represents the result of a wildcard directory match
|
||||
type wildcardDirectoryMatch struct {
|
||||
Key string
|
||||
Path string
|
||||
Recursive bool
|
||||
}
|
||||
|
||||
func getWildcardDirectoryFromSpec(spec string, useCaseSensitiveFileNames bool) *wildcardDirectoryMatch {
|
||||
// Find the first occurrence of a wildcard character
|
||||
firstWildcard := strings.IndexAny(spec, "*?")
|
||||
if firstWildcard != -1 {
|
||||
// Find the last directory separator before the wildcard
|
||||
lastSepBeforeWildcard := strings.LastIndexByte(spec[:firstWildcard], tspath.DirectorySeparator)
|
||||
if lastSepBeforeWildcard != -1 {
|
||||
path := spec[:lastSepBeforeWildcard]
|
||||
lastDirectorySeparatorIndex := strings.LastIndexByte(spec, tspath.DirectorySeparator)
|
||||
|
||||
// Determine if this should be watched recursively:
|
||||
// recursive if the wildcard appears in a directory segment (not just the final file segment)
|
||||
recursive := firstWildcard < lastDirectorySeparatorIndex
|
||||
|
||||
return &wildcardDirectoryMatch{
|
||||
Key: toCanonicalKey(path, useCaseSensitiveFileNames),
|
||||
Path: path,
|
||||
Recursive: recursive,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if lastSepIndex := strings.LastIndexByte(spec, tspath.DirectorySeparator); lastSepIndex != -1 {
|
||||
lastSegment := spec[lastSepIndex+1:]
|
||||
if vfsmatch.IsImplicitGlob(lastSegment) {
|
||||
path := tspath.RemoveTrailingDirectorySeparator(spec)
|
||||
return &wildcardDirectoryMatch{
|
||||
Key: toCanonicalKey(path, useCaseSensitiveFileNames),
|
||||
Path: path,
|
||||
Recursive: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user