@@ -711,7 +711,7 @@ namespace ts.Completions.StringCompletions {
711
711
extensionOptions ,
712
712
host ,
713
713
keys ,
714
- key => getPatternFromFirstMatchingCondition ( exports [ key ] , conditions ) ,
714
+ key => singleElementArray ( getPatternFromFirstMatchingCondition ( exports [ key ] , conditions ) ) ,
715
715
comparePatternKeys ) ;
716
716
return ;
717
717
}
@@ -726,15 +726,15 @@ namespace ts.Completions.StringCompletions {
726
726
return arrayFrom ( result . values ( ) ) ;
727
727
}
728
728
729
- function getPatternFromFirstMatchingCondition ( target : unknown , conditions : readonly string [ ] ) : [ string ] | undefined {
729
+ function getPatternFromFirstMatchingCondition ( target : unknown , conditions : readonly string [ ] ) : string | undefined {
730
730
if ( typeof target === "string" ) {
731
- return [ target ] ;
731
+ return target ;
732
732
}
733
733
if ( target && typeof target === "object" && ! isArray ( target ) ) {
734
734
for ( const condition in target ) {
735
735
if ( condition === "default" || conditions . indexOf ( condition ) > - 1 || isApplicableVersionedTypesKey ( conditions , condition ) ) {
736
736
const pattern = ( target as MapLike < unknown > ) [ condition ] ;
737
- return typeof pattern === "string" ? [ pattern ] : undefined ;
737
+ return getPatternFromFirstMatchingCondition ( pattern , conditions ) ;
738
738
}
739
739
}
740
740
}
@@ -804,27 +804,31 @@ namespace ts.Completions.StringCompletions {
804
804
const baseDirectory = normalizePath ( combinePaths ( packageDirectory , expandedPrefixDirectory ) ) ;
805
805
const completePrefix = fragmentHasPath ? baseDirectory : ensureTrailingDirectorySeparator ( baseDirectory ) + normalizedPrefixBase ;
806
806
807
- // If we have a suffix of at least a whole filename (i.e., not just an extension), then we need
808
- // to read the directory all the way down to see which directories contain a file matching that suffix.
809
- const suffixHasFilename = normalizedSuffix && containsSlash ( normalizedSuffix ) ;
810
- const includeGlob = suffixHasFilename ? "**/*" : "./*" ;
807
+ // If we have a suffix, then we read the directory all the way down to avoid returning completions for
808
+ // directories that don't contain files that would match the suffix. A previous comment here was concerned
809
+ // about the case where `normalizedSuffix` includes a `?` character, which should be interpreted literally,
810
+ // but will match any single character as part of the `include` pattern in `tryReadDirectory`. This is not
811
+ // a problem, because (in the extremely unusual circumstance where the suffix has a `?` in it) a `?`
812
+ // interpreted as "any character" can only return *too many* results as compared to the literal
813
+ // interpretation, so we can filter those superfluous results out via `trimPrefixAndSuffix` as we've always
814
+ // done.
815
+ const includeGlob = normalizedSuffix ? "**/*" + normalizedSuffix : "./*" ;
811
816
812
817
const matches = mapDefined ( tryReadDirectory ( host , baseDirectory , extensionOptions . extensions , /*exclude*/ undefined , [ includeGlob ] ) , match => {
813
818
const trimmedWithPattern = trimPrefixAndSuffix ( match ) ;
814
819
if ( trimmedWithPattern ) {
815
820
if ( containsSlash ( trimmedWithPattern ) ) {
816
- return directoryResult ( getPathComponents ( trimmedWithPattern ) [ 0 ] ) ;
821
+ return directoryResult ( getPathComponents ( removeLeadingDirectorySeparator ( trimmedWithPattern ) ) [ 1 ] ) ;
817
822
}
818
823
const { name, extension } = getFilenameWithExtensionOption ( trimmedWithPattern , host . getCompilationSettings ( ) , extensionOptions . includeExtensionsOption ) ;
819
824
return nameAndKind ( name , ScriptElementKind . scriptElement , extension ) ;
820
825
}
821
826
} ) ;
822
827
823
- // If the suffix had a whole filename in it, we already recursively searched for all possible files
824
- // that could match it and returned the directories that could possibly lead to matches. Otherwise,
825
- // assume any directory could have something valid to import (not a great assumption - we could
826
- // consider doing a whole glob more often and caching the results?)
827
- const directories = suffixHasFilename
828
+ // If we had a suffix, we already recursively searched for all possible files that could match
829
+ // it and returned the directories leading to those files. Otherwise, assume any directory could
830
+ // have something valid to import.
831
+ const directories = normalizedSuffix
828
832
? emptyArray
829
833
: mapDefined ( tryGetDirectories ( host , baseDirectory ) , dir => dir === "node_modules" ? undefined : directoryResult ( dir ) ) ;
830
834
return [ ...matches , ...directories ] ;
0 commit comments