namespace ts . codefix { export const importFixName = "import" ; const importFixId = "fixMissingImport" ; const errorCodes = [ Diagnostics . Cannot_find_name_0 . code , Diagnostics . Cannot_find_name_0_Did_you_mean_1 . code , Diagnostics . Cannot_find_name_0_Did_you_mean_the_instance_member_this_0 . code , Diagnostics . Cannot_find_name_0_Did_you_mean_the_static_member_1_0 . code , Diagnostics . Cannot_find_namespace_0 . code , Diagnostics . _0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead . code , Diagnostics . _0_only_refers_to_a_type_but_is_being_used_as_a_value_here . code , Diagnostics . No_value_exists_in_scope_for_the_shorthand_property_0_Either_declare_one_or_provide_an_initializer . code ] ; registerCodeFix ( { errorCodes , getCodeActions ( context ) { const { errorCode , preferences , sourceFile , span , program } = context ; const info = getFixesInfo ( context , errorCode , span . start , true ) ; if ( ! info ) return undefined ; const { fixes , symbolName } = info ; const quotePreference = getQuotePreference ( sourceFile , preferences ) ; return fixes . map ( fix => codeActionForFix ( context , sourceFile , symbolName , fix , quotePreference , program . getCompilerOptions ( ) ) ) ; } , fixIds : [ importFixId ] , getAllCodeActions : context => { const { sourceFile , program , preferences , host } = context ; const importAdder = createImportAdderWorker ( sourceFile , program , true , preferences , host ) ; eachDiagnostic ( context , errorCodes , diag => importAdder . addImportFromDiagnostic ( diag , context ) ) ; return createCombinedCodeActions ( textChanges . ChangeTracker . with ( context , importAdder . writeFixes ) ) ; } , } ) ; export interface ImportAdder { hasFixes ( ) : boolean ; addImportFromDiagnostic : ( diagnostic : DiagnosticWithLocation , context : CodeFixContextBase ) => void ; addImportFromExportedSymbol : ( exportedSymbol : Symbol , isValidTypeOnlyUseSite ? : boolean ) => void ; writeFixes : ( changeTracker : textChanges . ChangeTracker ) => void ; } export function createImportAdder ( sourceFile , program , preferences , host ) { return createImportAdderWorker ( sourceFile , program , false , preferences , host ) ; } interface AddToExistingState { readonly importClauseOrBindingPattern : ImportClause | ObjectBindingPattern ; defaultImport : Import | undefined ; readonly namedImports : ESMap < string , AddAsTypeOnly > ; } function createImportAdderWorker ( sourceFile , program , useAutoImportProvider , preferences , host ) { const compilerOptions = program . getCompilerOptions ( ) ; const addToNamespace = [ ] ; const importType = [ ] ; /** Keys are import clause node IDs. */ const addToExisting = new Map < string , AddToExistingState > ( ) ; type NewImportsKey = `${ 0 | 1 }|${ string }` ; /** Use `getNewImportEntry` for access */ const newImports = new Map < NewImportsKey , Mutable < ImportsCollection & { useRequire : boolean ; } > > ( ) ; return { addImportFromDiagnostic , addImportFromExportedSymbol , writeFixes , hasFixes } ; function addImportFromDiagnostic ( diagnostic , context ) { const info = getFixesInfo ( context , diagnostic . code , diagnostic . start , useAutoImportProvider ) ; if ( ! info || ! info . fixes . length ) return ; addImport ( info ) ; } function addImportFromExportedSymbol ( exportedSymbol , isValidTypeOnlyUseSite ? ) { const moduleSymbol = Debug . checkDefined ( exportedSymbol . parent ) ; const symbolName = getNameForExportedSymbol ( exportedSymbol , getEmitScriptTarget ( compilerOptions ) ) ; const checker = program . getTypeChecker ( ) ; const symbol = checker . getMergedSymbol ( skipAlias ( exportedSymbol , checker ) ) ; const exportInfos = getAllReExportingModules ( sourceFile , symbol , moduleSymbol , symbolName , host , program , preferences , useAutoImportProvider ) ; const useRequire = shouldUseRequire ( sourceFile , program ) ; const fix = getImportFixForSymbol ( sourceFile , exportInfos , moduleSymbol , symbolName , program , undefined , ! ! isValidTypeOnlyUseSite , useRequire , host , preferences ) ; if ( fix ) { addImport ( { fixes : [ fix ] , symbolName } ) ; } } function addImport ( info ) { const { fixes , symbolName } = info ; const fix = first ( fixes ) ; switch ( fix . kind ) { case ImportFixKind . UseNamespace : addToNamespace . push ( fix ) ; break ; case ImportFixKind . JsdocTypeImport : importType . push ( fix ) ; break ; case ImportFixKind . AddToExisting : { const { importClauseOrBindingPattern , importKind , addAsTypeOnly } = fix ; const key = String ( getNodeId ( importClauseOrBindingPattern ) ) ; let entry = addToExisting . get ( key ) ; if ( ! entry ) { addToExisting . set ( key , entry = { importClauseOrBindingPattern , defaultImport : undefined , namedImports : new Map ( ) } ) ; } if ( importKind === ImportKind . Named ) { const prevValue = entry ?. namedImports . get ( symbolName ) ; entry . namedImports . set ( symbolName , reduceAddAsTypeOnlyValues ( prevValue , addAsTypeOnly ) ) ; } else { Debug . assert ( entry . defaultImport === undefined || entry . defaultImport . name === symbolName , "(Add to Existing) Default import should be missing or match symbolName" ) ; entry . defaultImport = { name : symbolName , addAsTypeOnly : reduceAddAsTypeOnlyValues ( entry . defaultImport ?. addAsTypeOnly , addAsTypeOnly ) , } ; } break ; } case ImportFixKind . AddNew : { const { moduleSpecifier , importKind , useRequire , addAsTypeOnly } = fix ; const entry = getNewImportEntry ( moduleSpecifier , importKind , useRequire , addAsTypeOnly ) ; Debug . assert ( entry . useRequire === useRequire , "(Add new) Tried to add an `import` and a `require` for the same module" ) ; switch ( importKind ) { case ImportKind . Default : Debug . assert ( entry . defaultImport === undefined || entry . defaultImport . name === symbolName , "(Add new) Default import should be missing or match symbolName" ) ; entry . defaultImport = { name : symbolName , addAsTypeOnly : reduceAddAsTypeOnlyValues ( entry . defaultImport ?. addAsTypeOnly , addAsTypeOnly ) } ; break ; case ImportKind . Named : const prevValue = ( entry . namedImports ||= new Map ( ) ) . get ( symbolName ) ; entry . namedImports . set ( symbolName , reduceAddAsTypeOnlyValues ( prevValue , addAsTypeOnly ) ) ; break ; case ImportKind . CommonJS : case ImportKind . Namespace : Debug . assert ( entry . namespaceLikeImport === undefined || entry . namespaceLikeImport . name === symbolName , "Namespacelike import shoudl be missing or match symbolName" ) ; entry . namespaceLikeImport = { importKind , name : symbolName , addAsTypeOnly } ; break ; } break ; } default : Debug . assertNever ( fix , `fix wasn't never - got kind ${ ( fix as ImportFix ) . kind }` ) ; } function reduceAddAsTypeOnlyValues ( prevValue , newValue ) { return Math . max ( prevValue ?? 0 , newValue ) ; } function getNewImportEntry ( moduleSpecifier , importKind , useRequire , addAsTypeOnly ) { const typeOnlyKey = newImportsKey ( moduleSpecifier , true ) ; const nonTypeOnlyKey = newImportsKey ( moduleSpecifier , false ) ; const typeOnlyEntry = newImports . get ( typeOnlyKey ) ; const nonTypeOnlyEntry = newImports . get ( nonTypeOnlyKey ) ; const newEntry = { defaultImport : undefined , namedImports : undefined , namespaceLikeImport : undefined , useRequire } ; if ( importKind === ImportKind . Default && addAsTypeOnly === AddAsTypeOnly . Required ) { if ( typeOnlyEntry ) return typeOnlyEntry ; newImports . set ( typeOnlyKey , newEntry ) ; return newEntry ; } if ( addAsTypeOnly === AddAsTypeOnly . Allowed && ( typeOnlyEntry || nonTypeOnlyEntry ) ) { return ( typeOnlyEntry || nonTypeOnlyEntry ) ! ; } if ( nonTypeOnlyEntry ) { return nonTypeOnlyEntry ; } newImports . set ( nonTypeOnlyKey , newEntry ) ; return newEntry ; } function newImportsKey ( moduleSpecifier , topLevelTypeOnly ) { return `${ topLevelTypeOnly ? 1 : 0 }|${ moduleSpecifier }` ; } } function writeFixes ( changeTracker ) { const quotePreference = getQuotePreference ( sourceFile , preferences ) ; for ( const fix of addToNamespace ) { addNamespaceQualifier ( changeTracker , sourceFile , fix ) ; } for ( const fix of importType ) { addImportType ( changeTracker , sourceFile , fix , quotePreference ) ; } addToExisting . forEach ( ( { importClauseOrBindingPattern , defaultImport , namedImports } ) => { doAddExistingFix ( changeTracker , sourceFile , importClauseOrBindingPattern , defaultImport , arrayFrom ( namedImports . entries ( ) , ( [ name , addAsTypeOnly ] ) => ( { addAsTypeOnly , name } ) ) , compilerOptions ) ; } ) ; let newDeclarations ; newImports . forEach ( ( { useRequire , defaultImport , namedImports , namespaceLikeImport } , key ) => { const moduleSpecifier = key . slice ( 2 ) ; const getDeclarations = useRequire ? getNewRequires : getNewImports ; const declarations = getDeclarations ( moduleSpecifier , quotePreference , defaultImport , namedImports && arrayFrom ( namedImports . entries ( ) , ( [ name , addAsTypeOnly ] ) => ( { addAsTypeOnly , name } ) ) , namespaceLikeImport ) ; newDeclarations = combine ( newDeclarations , declarations ) ; } ) ; if ( newDeclarations ) { insertImports ( changeTracker , sourceFile , newDeclarations , true ) ; } } function hasFixes ( ) { return addToNamespace . length > 0 || importType . length > 0 || addToExisting . size > 0 || newImports . size > 0 ; } } const enum ImportFixKind { UseNamespace , JsdocTypeImport , AddToExisting , AddNew } const enum AddAsTypeOnly { Allowed = 1 << 0 , Required = 1 << 1 , NotAllowed = 1 << 2 } type ImportFix = FixUseNamespaceImport | FixAddJsdocTypeImport | FixAddToExistingImport | FixAddNewImport ; interface FixUseNamespaceImport { readonly kind : ImportFixKind . UseNamespace ; readonly namespacePrefix : string ; readonly position : number ; readonly moduleSpecifier : string ; } interface FixAddJsdocTypeImport { readonly kind : ImportFixKind . JsdocTypeImport ; readonly moduleSpecifier : string ; readonly position : number ; readonly exportInfo : SymbolExportInfo ; } interface FixAddToExistingImport { readonly kind : ImportFixKind . AddToExisting ; readonly importClauseOrBindingPattern : ImportClause | ObjectBindingPattern ; readonly moduleSpecifier : string ; readonly importKind : ImportKind . Default | ImportKind . Named ; readonly addAsTypeOnly : AddAsTypeOnly ; } interface FixAddNewImport { readonly kind : ImportFixKind . AddNew ; readonly moduleSpecifier : string ; readonly importKind : ImportKind ; readonly addAsTypeOnly : AddAsTypeOnly ; readonly useRequire : boolean ; readonly exportInfo ? : SymbolExportInfo ; } /** Information needed to augment an existing import declaration. */ interface FixAddToExistingImportInfo { readonly declaration : AnyImportOrRequire ; readonly importKind : ImportKind ; readonly targetFlags : SymbolFlags ; readonly symbol : Symbol ; } export function getImportCompletionAction ( targetSymbol , moduleSymbol , sourceFile , symbolName , host , program , formatContext , position , preferences ) { const compilerOptions = program . getCompilerOptions ( ) ; const exportInfos = pathIsBareSpecifier ( stripQuotes ( moduleSymbol . name ) ) ? [ getSymbolExportInfoForSymbol ( targetSymbol , moduleSymbol , program , host ) ] : getAllReExportingModules ( sourceFile , targetSymbol , moduleSymbol , symbolName , host , program , preferences , true ) ; const useRequire = shouldUseRequire ( sourceFile , program ) ; const isValidTypeOnlyUseSite = isValidTypeOnlyAliasUseSite ( getTokenAtPosition ( sourceFile , position ) ) ; const fix = Debug . checkDefined ( getImportFixForSymbol ( sourceFile , exportInfos , moduleSymbol , symbolName , program , position , isValidTypeOnlyUseSite , useRequire , host , preferences ) ) ; return { moduleSpecifier : fix . moduleSpecifier , codeAction : codeFixActionToCodeAction ( codeActionForFix ( { host , formatContext , preferences } , sourceFile , symbolName , fix , getQuotePreference ( sourceFile , preferences ) , compilerOptions ) ) } ; } function getImportFixForSymbol ( sourceFile , exportInfos , moduleSymbol , symbolName , program , position , isValidTypeOnlyUseSite , useRequire , host , preferences ) { Debug . assert ( exportInfos . some ( info => info . moduleSymbol === moduleSymbol || info . symbol . parent === moduleSymbol ) , "Some exportInfo should match the specified moduleSymbol" ) ; return getBestFix ( getImportFixes ( exportInfos , symbolName , position , isValidTypeOnlyUseSite , useRequire , program , sourceFile , host , preferences ) , sourceFile , program , host , preferences ) ; } function codeFixActionToCodeAction ( { description , changes , commands } ) { return { description , changes , commands } ; } function getSymbolExportInfoForSymbol ( symbol , moduleSymbol , program , host ) { const compilerOptions = program . getCompilerOptions ( ) ; const mainProgramInfo = getInfoWithChecker ( program . getTypeChecker ( ) , false ) ; if ( mainProgramInfo ) { return mainProgramInfo ; } const autoImportProvider = host . getPackageJsonAutoImportProvider ?. ( ) ?. getTypeChecker ( ) ; return Debug . checkDefined ( autoImportProvider && getInfoWithChecker ( autoImportProvider , true ) , `Could not find symbol in specified module for code actions` ) ; function getInfoWithChecker ( checker , isFromPackageJson ) { const defaultInfo = getDefaultLikeExportInfo ( moduleSymbol , checker , compilerOptions ) ; if ( defaultInfo && skipAlias ( defaultInfo . symbol , checker ) === symbol ) { return { symbol : defaultInfo . symbol , moduleSymbol , moduleFileName : undefined , exportKind : defaultInfo . exportKind , targetFlags : skipAlias ( symbol , checker ) . flags , isFromPackageJson } ; } const named = checker . tryGetMemberInModuleExportsAndProperties ( symbol . name , moduleSymbol ) ; if ( named && skipAlias ( named , checker ) === symbol ) { return { symbol : named , moduleSymbol , moduleFileName : undefined , exportKind : ExportKind . Named , targetFlags : skipAlias ( symbol , checker ) . flags , isFromPackageJson } ; } } } function getAllReExportingModules ( importingFile , targetSymbol , exportingModuleSymbol , symbolName , host , program , preferences , useAutoImportProvider ) { const result = [ ] ; const compilerOptions = program . getCompilerOptions ( ) ; const getModuleSpecifierResolutionHost = memoizeOne ( ( isFromPackageJson ) => { return createModuleSpecifierResolutionHost ( isFromPackageJson ? host . getPackageJsonAutoImportProvider ! ( ) ! : program , host ) ; } ) ; forEachExternalModuleToImportFrom ( program , host , useAutoImportProvider , ( moduleSymbol , moduleFile , program , isFromPackageJson ) => { const checker = program . getTypeChecker ( ) ; if ( moduleFile && moduleSymbol !== exportingModuleSymbol && startsWith ( importingFile . fileName , getDirectoryPath ( moduleFile . fileName ) ) ) { return ; } const defaultInfo = getDefaultLikeExportInfo ( moduleSymbol , checker , compilerOptions ) ; if ( defaultInfo && ( defaultInfo . name === symbolName || moduleSymbolToValidIdentifier ( moduleSymbol , getEmitScriptTarget ( compilerOptions ) ) === symbolName ) && skipAlias ( defaultInfo . symbol , checker ) === targetSymbol && isImportable ( program , moduleFile , isFromPackageJson ) ) { result . push ( { symbol : defaultInfo . symbol , moduleSymbol , moduleFileName : moduleFile ?. fileName , exportKind : defaultInfo . exportKind , targetFlags : skipAlias ( defaultInfo . symbol , checker ) . flags , isFromPackageJson } ) ; } for ( const exported of checker . getExportsAndPropertiesOfModule ( moduleSymbol ) ) { if ( exported . name === symbolName && checker . getMergedSymbol ( skipAlias ( exported , checker ) ) === targetSymbol && isImportable ( program , moduleFile , isFromPackageJson ) ) { result . push ( { symbol : exported , moduleSymbol , moduleFileName : moduleFile ?. fileName , exportKind : ExportKind . Named , targetFlags : skipAlias ( exported , checker ) . flags , isFromPackageJson } ) ; } } } ) ; return result ; function isImportable ( program , moduleFile , isFromPackageJson ) { return ! moduleFile || isImportableFile ( program , importingFile , moduleFile , preferences , undefined , getModuleSpecifierResolutionHost ( isFromPackageJson ) , host . getModuleSpecifierCache ?. ( ) ) ; } } export function getModuleSpecifierForBestExportInfo ( exportInfo , importingFile , program , host , preferences , fromCacheOnly ? ) { const { fixes , computedWithoutCacheCount } = getNewImportFixes ( program , importingFile , undefined , false , false , exportInfo , host , preferences , fromCacheOnly ) ; const result = getBestFix ( fixes , importingFile , program , host , preferences ) ; return result && { ... result , computedWithoutCacheCount } ; } function getImportFixes ( exportInfos , symbolName , /** undefined only for missing JSX namespace */ position , isValidTypeOnlyUseSite , useRequire , program , sourceFile , host , preferences ) { const checker = program . getTypeChecker ( ) ; const existingImports = flatMap ( exportInfos , info => getExistingImportDeclarations ( info , checker , sourceFile , program . getCompilerOptions ( ) ) ) ; const useNamespace = position === undefined ? undefined : tryUseExistingNamespaceImport ( existingImports , symbolName , position , checker ) ; const addToExisting = tryAddToExistingImport ( existingImports , isValidTypeOnlyUseSite , checker , program . getCompilerOptions ( ) ) ; const addImport = addToExisting ? [ addToExisting ] : getFixesForAddImport ( exportInfos , existingImports , program , sourceFile , position , isValidTypeOnlyUseSite , useRequire , host , preferences ) ; return [ ... ( useNamespace ? [ useNamespace ] : emptyArray ) , ... addImport ] ; } function tryUseExistingNamespaceImport ( existingImports , symbolName , position , checker ) { return firstDefined ( existingImports , ( { declaration } ) : FixUseNamespaceImport | undefined => { const namespacePrefix = getNamespaceLikeImportText ( declaration ) ; const moduleSpecifier = tryGetModuleSpecifierFromDeclaration ( declaration ) ; if ( namespacePrefix && moduleSpecifier ) { const moduleSymbol = getTargetModuleFromNamespaceLikeImport ( declaration , checker ) ; if ( moduleSymbol && moduleSymbol . exports ! . has ( escapeLeadingUnderscores ( symbolName ) ) ) { return { kind : ImportFixKind . UseNamespace , namespacePrefix , position , moduleSpecifier } ; } } } ) ; } function getTargetModuleFromNamespaceLikeImport ( declaration , checker ) { switch ( declaration . kind ) { case SyntaxKind . VariableDeclaration : return checker . resolveExternalModuleName ( declaration . initializer . arguments [ 0 ] ) ; case SyntaxKind . ImportEqualsDeclaration : return checker . getAliasedSymbol ( declaration . symbol ) ; case SyntaxKind . ImportDeclaration : const namespaceImport = tryCast ( declaration . importClause ?. namedBindings , isNamespaceImport ) ; return namespaceImport && checker . getAliasedSymbol ( namespaceImport . symbol ) ; default : return Debug . assertNever ( declaration ) ; } } function getNamespaceLikeImportText ( declaration ) { switch ( declaration . kind ) { case SyntaxKind . VariableDeclaration : return tryCast ( declaration . name , isIdentifier ) ?. text ; case SyntaxKind . ImportEqualsDeclaration : return declaration . name . text ; case SyntaxKind . ImportDeclaration : return tryCast ( declaration . importClause ?. namedBindings , isNamespaceImport ) ?. name . text ; default : return Debug . assertNever ( declaration ) ; } } function getAddAsTypeOnly ( isValidTypeOnlyUseSite , isForNewImportDeclaration , symbol , targetFlags , checker , compilerOptions ) { if ( ! isValidTypeOnlyUseSite ) { return AddAsTypeOnly . NotAllowed ; } if ( isForNewImportDeclaration && compilerOptions . importsNotUsedAsValues === ImportsNotUsedAsValues . Error ) { return AddAsTypeOnly . Required ; } if ( compilerOptions . isolatedModules && compilerOptions . preserveValueImports && ( ! ( targetFlags & SymbolFlags . Value ) || ! ! checker . getTypeOnlyAliasDeclaration ( symbol ) ) ) { return AddAsTypeOnly . Required ; } return AddAsTypeOnly . Allowed ; } function tryAddToExistingImport ( existingImports , isValidTypeOnlyUseSite , checker , compilerOptions ) { return firstDefined ( existingImports , ( { declaration , importKind , symbol , targetFlags } ) : FixAddToExistingImport | undefined => { if ( importKind === ImportKind . CommonJS || importKind === ImportKind . Namespace || declaration . kind === SyntaxKind . ImportEqualsDeclaration ) { return undefined ; } if ( declaration . kind === SyntaxKind . VariableDeclaration ) { return ( importKind === ImportKind . Named || importKind === ImportKind . Default ) && declaration . name . kind === SyntaxKind . ObjectBindingPattern ? { kind : ImportFixKind . AddToExisting , importClauseOrBindingPattern : declaration . name , importKind , moduleSpecifier : declaration . initializer . arguments [ 0 ] . text , addAsTypeOnly : AddAsTypeOnly . NotAllowed } : undefined ; } const { importClause } = declaration ; if ( ! importClause || ! isStringLiteralLike ( declaration . moduleSpecifier ) ) return undefined ; const { name , namedBindings } = importClause ; if ( importClause . isTypeOnly && ! ( importKind === ImportKind . Named && namedBindings ) ) return undefined ; const addAsTypeOnly = getAddAsTypeOnly ( isValidTypeOnlyUseSite , false , symbol , targetFlags , checker , compilerOptions ) ; if ( importKind === ImportKind . Default && ( name || addAsTypeOnly === AddAsTypeOnly . Required && namedBindings ) ) return undefined ; if ( importKind === ImportKind . Named && namedBindings ?. kind === SyntaxKind . NamespaceImport ) return undefined ; return { kind : ImportFixKind . AddToExisting , importClauseOrBindingPattern : importClause , importKind , moduleSpecifier : declaration . moduleSpecifier . text , addAsTypeOnly , } ; } ) ; } function getExistingImportDeclarations ( { moduleSymbol , exportKind , targetFlags , symbol } , checker , importingFile , compilerOptions ) { if ( ! ( targetFlags & SymbolFlags . Value ) && isSourceFileJS ( importingFile ) ) return emptyArray ; const importKind = getImportKind ( importingFile , exportKind , compilerOptions ) ; return mapDefined ( importingFile . imports , ( moduleSpecifier ) : FixAddToExistingImportInfo | undefined => { const i = importFromModuleSpecifier ( moduleSpecifier ) ; if ( isRequireVariableDeclaration ( i . parent ) ) { return checker . resolveExternalModuleName ( moduleSpecifier ) === moduleSymbol ? { declaration : i . parent , importKind , symbol , targetFlags } : undefined ; } if ( i . kind === SyntaxKind . ImportDeclaration || i . kind === SyntaxKind . ImportEqualsDeclaration ) { return checker . getSymbolAtLocation ( moduleSpecifier ) === moduleSymbol ? { declaration : i , importKind , symbol , targetFlags } : undefined ; } } ) ; } function shouldUseRequire ( sourceFile , program ) { if ( ! isSourceFileJS ( sourceFile ) ) { return false ; } if ( sourceFile . commonJsModuleIndicator && ! sourceFile . externalModuleIndicator ) return true ; if ( sourceFile . externalModuleIndicator && ! sourceFile . commonJsModuleIndicator ) return false ; const compilerOptions = program . getCompilerOptions ( ) ; if ( compilerOptions . configFile ) { return getEmitModuleKind ( compilerOptions ) < ModuleKind . ES2015 ; } for ( const otherFile of program . getSourceFiles ( ) ) { if ( otherFile === sourceFile || ! isSourceFileJS ( otherFile ) || program . isSourceFileFromExternalLibrary ( otherFile ) ) continue ; if ( otherFile . commonJsModuleIndicator && ! otherFile . externalModuleIndicator ) return true ; if ( otherFile . externalModuleIndicator && ! otherFile . commonJsModuleIndicator ) return false ; } return true ; } function getNewImportFixes ( program , sourceFile , position , isValidTypeOnlyUseSite , useRequire , moduleSymbols , host , preferences , fromCacheOnly ? ) { const isJs = isSourceFileJS ( sourceFile ) ; const compilerOptions = program . getCompilerOptions ( ) ; const moduleSpecifierResolutionHost = createModuleSpecifierResolutionHost ( program , host ) ; const getChecker = memoizeOne ( ( isFromPackageJson ) => isFromPackageJson ? host . getPackageJsonAutoImportProvider ! ( ) ! . getTypeChecker ( ) : program . getTypeChecker ( ) ) ; const getModuleSpecifiers = fromCacheOnly ? ( moduleSymbol ) => ( { moduleSpecifiers : moduleSpecifiers . tryGetModuleSpecifiersFromCache ( moduleSymbol , sourceFile , moduleSpecifierResolutionHost , preferences ) , computedWithoutCache : false } ) : ( moduleSymbol , checker ) => moduleSpecifiers . getModuleSpecifiersWithCacheInfo ( moduleSymbol , checker , compilerOptions , sourceFile , moduleSpecifierResolutionHost , preferences ) ; let computedWithoutCacheCount = 0 ; const fixes = flatMap ( moduleSymbols , exportInfo => { const checker = getChecker ( exportInfo . isFromPackageJson ) ; const { computedWithoutCache , moduleSpecifiers } = getModuleSpecifiers ( exportInfo . moduleSymbol , checker ) ; const importedSymbolHasValueMeaning = ! ! ( exportInfo . targetFlags & SymbolFlags . Value ) ; const addAsTypeOnly = getAddAsTypeOnly ( isValidTypeOnlyUseSite , true , exportInfo . symbol , exportInfo . targetFlags , checker , compilerOptions ) ; computedWithoutCacheCount += computedWithoutCache ? 1 : 0 ; return moduleSpecifiers ?. map ( ( moduleSpecifier ) : FixAddNewImport | FixAddJsdocTypeImport => ! importedSymbolHasValueMeaning && isJs && position !== undefined ? { kind : ImportFixKind . JsdocTypeImport , moduleSpecifier , position , exportInfo } : { kind : ImportFixKind . AddNew , moduleSpecifier , importKind : getImportKind ( sourceFile , exportInfo . exportKind , compilerOptions ) , useRequire , addAsTypeOnly , exportInfo , } ) ; } ) ; return { computedWithoutCacheCount , fixes } ; } function getFixesForAddImport ( exportInfos , existingImports , program , sourceFile , position , isValidTypeOnlyUseSite , useRequire , host , preferences ) { const existingDeclaration = firstDefined ( existingImports , info => newImportInfoFromExistingSpecifier ( info , isValidTypeOnlyUseSite , useRequire , program . getTypeChecker ( ) , program . getCompilerOptions ( ) ) ) ; return existingDeclaration ? [ existingDeclaration ] : getNewImportFixes ( program , sourceFile , position , isValidTypeOnlyUseSite , useRequire , exportInfos , host , preferences ) . fixes ; } function newImportInfoFromExistingSpecifier ( { declaration , importKind , symbol , targetFlags } , isValidTypeOnlyUseSite , useRequire , checker , compilerOptions ) { const moduleSpecifier = tryGetModuleSpecifierFromDeclaration ( declaration ) ; if ( moduleSpecifier ) { const addAsTypeOnly = useRequire ? AddAsTypeOnly . NotAllowed : getAddAsTypeOnly ( isValidTypeOnlyUseSite , true , symbol , targetFlags , checker , compilerOptions ) ; return { kind : ImportFixKind . AddNew , moduleSpecifier , importKind , addAsTypeOnly , useRequire } ; } } interface FixesInfo { readonly fixes : readonly ImportFix [ ] ; readonly symbolName : string ; } function getFixesInfo ( context , errorCode , pos , useAutoImportProvider ) { const symbolToken = getTokenAtPosition ( context . sourceFile , pos ) ; const info = errorCode === Diagnostics . _0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead . code ? getFixesInfoForUMDImport ( context , symbolToken ) : isIdentifier ( symbolToken ) ? getFixesInfoForNonUMDImport ( context , symbolToken , useAutoImportProvider ) : undefined ; return info && { ... info , fixes : sortFixes ( info . fixes , context . sourceFile , context . program , context . host , context . preferences ) } ; } function sortFixes ( fixes , sourceFile , program , host , preferences ) { const { allowsImportingSpecifier } = createPackageJsonImportFilter ( sourceFile , preferences , host ) ; return sort ( fixes , ( a , b ) => compareValues ( a . kind , b . kind ) || compareModuleSpecifiers ( a , b , sourceFile , program , allowsImportingSpecifier ) ) ; } function getBestFix < T extends ImportFix > ( fixes , sourceFile , program , host , preferences ) { if ( ! some ( fixes ) ) return ; if ( fixes [ 0 ] . kind === ImportFixKind . UseNamespace || fixes [ 0 ] . kind === ImportFixKind . AddToExisting ) { return fixes [ 0 ] ; } const { allowsImportingSpecifier } = createPackageJsonImportFilter ( sourceFile , preferences , host ) ; return fixes . reduce ( ( best , fix ) => compareModuleSpecifiers ( fix , best , sourceFile , program , allowsImportingSpecifier ) === Comparison . LessThan ? fix : best ) ; } returns function compareModuleSpecifiers ( a , b , importingFile , program , allowsImportingSpecifier ) { if ( a . kind !== ImportFixKind . UseNamespace && b . kind !== ImportFixKind . UseNamespace ) { return compareBooleans ( allowsImportingSpecifier ( b . moduleSpecifier ) , allowsImportingSpecifier ( a . moduleSpecifier ) ) || compareNodeCoreModuleSpecifiers ( a . moduleSpecifier , b . moduleSpecifier , importingFile , program ) || compareBooleans ( isOnlyDotsAndSlashes ( a . moduleSpecifier ) , isOnlyDotsAndSlashes ( b . moduleSpecifier ) ) || compareNumberOfDirectorySeparators ( a . moduleSpecifier , b . moduleSpecifier ) ; } return Comparison . EqualTo ; } const notDotOrSlashPattern = /[^.\/]/ ; function isOnlyDotsAndSlashes ( path ) { return ! notDotOrSlashPattern . test ( path ) ; } function compareNodeCoreModuleSpecifiers ( a , b , importingFile , program ) { if ( startsWith ( a , "node:" ) && ! startsWith ( b , "node:" ) ) return shouldUseUriStyleNodeCoreModules ( importingFile , program ) ? Comparison . LessThan : Comparison . GreaterThan ; if ( startsWith ( b , "node:" ) && ! startsWith ( a , "node:" ) ) return shouldUseUriStyleNodeCoreModules ( importingFile , program ) ? Comparison . GreaterThan : Comparison . LessThan ; return Comparison . EqualTo ; } function getFixesInfoForUMDImport ( { sourceFile , program , host , preferences } , token ) { const checker = program . getTypeChecker ( ) ; const umdSymbol = getUmdSymbol ( token , checker ) ; if ( ! umdSymbol ) return undefined ; const symbol = checker . getAliasedSymbol ( umdSymbol ) ; const symbolName = umdSymbol . name ; const exportInfos = [ { symbol : umdSymbol , moduleSymbol : symbol , moduleFileName : undefined , exportKind : ExportKind . UMD , targetFlags : symbol . flags , isFromPackageJson : false } ] ; const useRequire = shouldUseRequire ( sourceFile , program ) ; const fixes = getImportFixes ( exportInfos , symbolName , isIdentifier ( token ) ? token . getStart ( sourceFile ) : undefined , false , useRequire , program , sourceFile , host , preferences ) ; return { fixes , symbolName } ; } function getUmdSymbol ( token , checker ) { const umdSymbol = isIdentifier ( token ) ? checker . getSymbolAtLocation ( token ) : undefined ; if ( isUMDExportSymbol ( umdSymbol ) ) return umdSymbol ; const { parent } = token ; return ( isJsxOpeningLikeElement ( parent ) && parent . tagName === token ) || isJsxOpeningFragment ( parent ) ? tryCast ( checker . resolveName ( checker . getJsxNamespace ( parent ) , isJsxOpeningLikeElement ( parent ) ? token : parent , SymbolFlags . Value , false ) , isUMDExportSymbol ) : undefined ; } param forceImportKeyword export function getImportKind ( importingFile , exportKind , compilerOptions , forceImportKeyword ? ) { switch ( exportKind ) { case ExportKind . Named : return ImportKind . Named ; case ExportKind . Default : return ImportKind . Default ; case ExportKind . ExportEquals : return getExportEqualsImportKind ( importingFile , compilerOptions , ! ! forceImportKeyword ) ; case ExportKind . UMD : return getUmdImportKind ( importingFile , compilerOptions , ! ! forceImportKeyword ) ; default : return Debug . assertNever ( exportKind ) ; } } function getUmdImportKind ( importingFile , compilerOptions , forceImportKeyword ) { if ( getAllowSyntheticDefaultImports ( compilerOptions ) ) { return ImportKind . Default ; } const moduleKind = getEmitModuleKind ( compilerOptions ) ; switch ( moduleKind ) { case ModuleKind . AMD : case ModuleKind . CommonJS : case ModuleKind . UMD : if ( isInJSFile ( importingFile ) ) { return isExternalModule ( importingFile ) || forceImportKeyword ? ImportKind . Namespace : ImportKind . CommonJS ; } return ImportKind . CommonJS ; case ModuleKind . System : case ModuleKind . ES2015 : case ModuleKind . ES2020 : case ModuleKind . ES2022 : case ModuleKind . ESNext : case ModuleKind . None : return ImportKind . Namespace ; case ModuleKind . Node12 : case ModuleKind . NodeNext : return importingFile . impliedNodeFormat === ModuleKind . ESNext ? ImportKind . Namespace : ImportKind . CommonJS ; default : return Debug . assertNever ( moduleKind , `Unexpected moduleKind ${ moduleKind }` ) ; } } function getFixesInfoForNonUMDImport ( { sourceFile , program , cancellationToken , host , preferences } , symbolToken , useAutoImportProvider ) { const checker = program . getTypeChecker ( ) ; const compilerOptions = program . getCompilerOptions ( ) ; const symbolName = getSymbolName ( sourceFile , checker , symbolToken , compilerOptions ) ; Debug . assert ( symbolName !== InternalSymbolName . Default , "'default' isn't a legal identifier and couldn't occur here" ) ; const isValidTypeOnlyUseSite = isValidTypeOnlyAliasUseSite ( symbolToken ) ; const useRequire = shouldUseRequire ( sourceFile , program ) ; const exportInfos = getExportInfos ( symbolName , getMeaningFromLocation ( symbolToken ) , cancellationToken , sourceFile , program , useAutoImportProvider , host , preferences ) ; const fixes = arrayFrom ( flatMapIterator ( exportInfos . entries ( ) , ( [ _ , exportInfos ] ) => getImportFixes ( exportInfos , symbolName , symbolToken . getStart ( sourceFile ) , isValidTypeOnlyUseSite , useRequire , program , sourceFile , host , preferences ) ) ) ; return { fixes , symbolName } ; } function jsxModeNeedsExplicitImport ( jsx ) { return jsx === JsxEmit . React || jsx === JsxEmit . ReactNative ; } function getSymbolName ( sourceFile , checker , symbolToken , compilerOptions ) { const parent = symbolToken . parent ; if ( ( isJsxOpeningLikeElement ( parent ) || isJsxClosingElement ( parent ) ) && parent . tagName === symbolToken && jsxModeNeedsExplicitImport ( compilerOptions . jsx ) ) { const jsxNamespace = checker . getJsxNamespace ( sourceFile ) ; if ( isIntrinsicJsxName ( symbolToken . text ) || ! checker . resolveName ( jsxNamespace , parent , SymbolFlags . Value , true ) ) { return jsxNamespace ; } } return symbolToken . text ; } function getExportInfos ( symbolName , currentTokenMeaning , cancellationToken , fromFile , program , useAutoImportProvider , host , preferences ) { const originalSymbolToExportInfos = createMultiMap < SymbolExportInfo > ( ) ; const packageJsonFilter = createPackageJsonImportFilter ( fromFile , preferences , host ) ; const moduleSpecifierCache = host . getModuleSpecifierCache ?. ( ) ; const getModuleSpecifierResolutionHost = memoizeOne ( ( isFromPackageJson ) => { return createModuleSpecifierResolutionHost ( isFromPackageJson ? host . getPackageJsonAutoImportProvider ! ( ) ! : program , host ) ; } ) ; function addSymbol ( moduleSymbol , toFile , exportedSymbol , exportKind , program , isFromPackageJson ) { const moduleSpecifierResolutionHost = getModuleSpecifierResolutionHost ( isFromPackageJson ) ; if ( toFile && isImportableFile ( program , fromFile , toFile , preferences , packageJsonFilter , moduleSpecifierResolutionHost , moduleSpecifierCache ) || ! toFile && packageJsonFilter . allowsImportingAmbientModule ( moduleSymbol , moduleSpecifierResolutionHost ) ) { const checker = program . getTypeChecker ( ) ; originalSymbolToExportInfos . add ( getUniqueSymbolId ( exportedSymbol , checker ) . toString ( ) , { symbol : exportedSymbol , moduleSymbol , moduleFileName : toFile ?. fileName , exportKind , targetFlags : skipAlias ( exportedSymbol , checker ) . flags , isFromPackageJson } ) ; } } forEachExternalModuleToImportFrom ( program , host , useAutoImportProvider , ( moduleSymbol , sourceFile , program , isFromPackageJson ) => { const checker = program . getTypeChecker ( ) ; cancellationToken . throwIfCancellationRequested ( ) ; const compilerOptions = program . getCompilerOptions ( ) ; const defaultInfo = getDefaultLikeExportInfo ( moduleSymbol , checker , compilerOptions ) ; if ( defaultInfo && ( defaultInfo . name === symbolName || moduleSymbolToValidIdentifier ( moduleSymbol , getEmitScriptTarget ( compilerOptions ) ) === symbolName ) && symbolHasMeaning ( defaultInfo . symbolForMeaning , currentTokenMeaning ) ) { addSymbol ( moduleSymbol , sourceFile , defaultInfo . symbol , defaultInfo . exportKind , program , isFromPackageJson ) ; } const exportSymbolWithIdenticalName = checker . tryGetMemberInModuleExportsAndProperties ( symbolName , moduleSymbol ) ; if ( exportSymbolWithIdenticalName && symbolHasMeaning ( exportSymbolWithIdenticalName , currentTokenMeaning ) ) { addSymbol ( moduleSymbol , sourceFile , exportSymbolWithIdenticalName , ExportKind . Named , program , isFromPackageJson ) ; } } ) ; return originalSymbolToExportInfos ; } function getExportEqualsImportKind ( importingFile , compilerOptions , forceImportKeyword ) { const allowSyntheticDefaults = getAllowSyntheticDefaultImports ( compilerOptions ) ; const isJS = isInJSFile ( importingFile ) ; if ( ! isJS && getEmitModuleKind ( compilerOptions ) >= ModuleKind . ES2015 ) { return allowSyntheticDefaults ? ImportKind . Default : ImportKind . Namespace ; } if ( isJS ) { return isExternalModule ( importingFile ) || forceImportKeyword ? allowSyntheticDefaults ? ImportKind . Default : ImportKind . Namespace : ImportKind . CommonJS ; } for ( const statement of importingFile . statements ) { if ( isImportEqualsDeclaration ( statement ) && ! nodeIsMissing ( statement . moduleReference ) ) { return ImportKind . CommonJS ; } } return allowSyntheticDefaults ? ImportKind . Default : ImportKind . CommonJS ; } function codeActionForFix ( context , sourceFile , symbolName , fix , quotePreference , compilerOptions ) { let diag ! ; const changes = textChanges . ChangeTracker . with ( context , tracker => { diag = codeActionForFixWorker ( tracker , sourceFile , symbolName , fix , quotePreference , compilerOptions ) ; } ) ; return createCodeFixAction ( importFixName , changes , diag , importFixId , Diagnostics . Add_all_missing_imports ) ; } function codeActionForFixWorker ( changes , sourceFile , symbolName , fix , quotePreference , compilerOptions ) { switch ( fix . kind ) { case ImportFixKind . UseNamespace : addNamespaceQualifier ( changes , sourceFile , fix ) ; return [ Diagnostics . Change_0_to_1 , symbolName , `${ fix . namespacePrefix }.${ symbolName }` ] ; case ImportFixKind . JsdocTypeImport : addImportType ( changes , sourceFile , fix , quotePreference ) ; return [ Diagnostics . Change_0_to_1 , symbolName , getImportTypePrefix ( fix . moduleSpecifier , quotePreference ) + symbolName ] ; case ImportFixKind . AddToExisting : { const { importClauseOrBindingPattern , importKind , addAsTypeOnly , moduleSpecifier } = fix ; doAddExistingFix ( changes , sourceFile , importClauseOrBindingPattern , importKind === ImportKind . Default ? { name : symbolName , addAsTypeOnly } : undefined , importKind === ImportKind . Named ? [ { name : symbolName , addAsTypeOnly } ] : emptyArray , compilerOptions ) ; const moduleSpecifierWithoutQuotes = stripQuotes ( moduleSpecifier ) ; return [ importKind === ImportKind . Default ? Diagnostics . Add_default_import_0_to_existing_import_declaration_from_1 : Diagnostics . Add_0_to_existing_import_declaration_from_1 , symbolName , moduleSpecifierWithoutQuotes ] ; } case ImportFixKind . AddNew : { const { importKind , moduleSpecifier , addAsTypeOnly , useRequire } = fix ; const getDeclarations = useRequire ? getNewRequires : getNewImports ; const defaultImport = importKind === ImportKind . Default ? { name : symbolName , addAsTypeOnly } : undefined ; const namedImports = importKind === ImportKind . Named ? [ { name : symbolName , addAsTypeOnly } ] : undefined ; const namespaceLikeImport = importKind === ImportKind . Namespace || importKind === ImportKind . CommonJS ? { importKind , name : symbolName , addAsTypeOnly } : undefined ; insertImports ( changes , sourceFile , getDeclarations ( moduleSpecifier , quotePreference , defaultImport , namedImports , namespaceLikeImport ) , true ) ; return [ importKind === ImportKind . Default ? Diagnostics . Import_default_0_from_module_1 : Diagnostics . Import_0_from_module_1 , symbolName , moduleSpecifier ] ; } default : return Debug . assertNever ( fix , `Unexpected fix kind ${ ( fix as ImportFix ) . kind }` ) ; } } function doAddExistingFix ( changes , sourceFile , clause , defaultImport , namedImports , compilerOptions ) { if ( clause . kind === SyntaxKind . ObjectBindingPattern ) { if ( defaultImport ) { addElementToBindingPattern ( clause , defaultImport . name , "default" ) ; } for ( const specifier of namedImports ) { addElementToBindingPattern ( clause , specifier . name , undefined ) ; } return ; } const promoteFromTypeOnly = clause . isTypeOnly && some ( [ defaultImport , ... namedImports ] , i => i ?. addAsTypeOnly === AddAsTypeOnly . NotAllowed ) ; const existingSpecifiers = clause . namedBindings && tryCast ( clause . namedBindings , isNamedImports ) ?. elements ; const convertExistingToTypeOnly = promoteFromTypeOnly && compilerOptions . preserveValueImports && compilerOptions . isolatedModules ; if ( defaultImport ) { Debug . assert ( ! clause . name , "Cannot add a default import to an import clause that already has one" ) ; changes . insertNodeAt ( sourceFile , clause . getStart ( sourceFile ) , factory . createIdentifier ( defaultImport . name ) , { suffix : ", " } ) ; } if ( namedImports . length ) { const newSpecifiers = stableSort ( namedImports . map ( namedImport => factory . createImportSpecifier ( ( ! clause . isTypeOnly || promoteFromTypeOnly ) && needsTypeOnly ( namedImport ) , undefined , factory . createIdentifier ( namedImport . name ) ) ) , OrganizeImports . compareImportOrExportSpecifiers ) ; if ( existingSpecifiers ?. length && OrganizeImports . importSpecifiersAreSorted ( existingSpecifiers ) ) { for ( const spec of newSpecifiers ) { const insertionIndex = convertExistingToTypeOnly && ! spec . isTypeOnly ? 0 : OrganizeImports . getImportSpecifierInsertionIndex ( existingSpecifiers , spec ) ; const prevSpecifier = ( clause . namedBindings as NamedImports ) . elements [ insertionIndex - 1 ] ; if ( prevSpecifier ) { changes . insertNodeInListAfter ( sourceFile , prevSpecifier , spec ) ; } else { changes . insertNodeBefore ( sourceFile , existingSpecifiers [ 0 ] , spec , ! positionsAreOnSameLine ( existingSpecifiers [ 0 ] . getStart ( ) , clause . parent . getStart ( ) , sourceFile ) ) ; } } } else if ( existingSpecifiers ?. length ) { for ( const spec of newSpecifiers ) { changes . insertNodeInListAfter ( sourceFile , last ( existingSpecifiers ) , spec , existingSpecifiers ) ; } } else { if ( newSpecifiers . length ) { const namedImports = factory . createNamedImports ( newSpecifiers ) ; if ( clause . namedBindings ) { changes . replaceNode ( sourceFile , clause . namedBindings , namedImports ) ; } else { changes . insertNodeAfter ( sourceFile , Debug . checkDefined ( clause . name , "Import clause must have either named imports or a default import" ) , namedImports ) ; } } } } if ( promoteFromTypeOnly ) { changes . delete ( sourceFile , getTypeKeywordOfTypeOnlyImport ( clause , sourceFile ) ) ; if ( convertExistingToTypeOnly && existingSpecifiers ) { for ( const specifier of existingSpecifiers ) { changes . insertModifierBefore ( sourceFile , SyntaxKind . TypeKeyword , specifier ) ; } } } function addElementToBindingPattern ( bindingPattern , name , propertyName ) { const element = factory . createBindingElement ( undefined , propertyName , name ) ; if ( bindingPattern . elements . length ) { changes . insertNodeInListAfter ( sourceFile , last ( bindingPattern . elements ) , element ) ; } else { changes . replaceNode ( sourceFile , bindingPattern , factory . createObjectBindingPattern ( [ element ] ) ) ; } } } function addNamespaceQualifier ( changes , sourceFile , { namespacePrefix , position } ) { changes . insertText ( sourceFile , position , namespacePrefix + "." ) ; } function addImportType ( changes , sourceFile , { moduleSpecifier , position } , quotePreference ) { changes . insertText ( sourceFile , position , getImportTypePrefix ( moduleSpecifier , quotePreference ) ) ; } function getImportTypePrefix ( moduleSpecifier , quotePreference ) { const quote = getQuoteFromPreference ( quotePreference ) ; return `import(${ quote }${ moduleSpecifier }${ quote }).` ; } interface Import { readonly name : string ; readonly addAsTypeOnly : AddAsTypeOnly ; } interface ImportsCollection { readonly defaultImport ? : Import ; readonly namedImports ? : ESMap < string , AddAsTypeOnly > ; readonly namespaceLikeImport ? : { readonly importKind : ImportKind . CommonJS | ImportKind . Namespace ; readonly name : string ; readonly addAsTypeOnly : AddAsTypeOnly ; } ; } function needsTypeOnly ( { addAsTypeOnly } ) { return addAsTypeOnly === AddAsTypeOnly . Required ; } function getNewImports ( moduleSpecifier , quotePreference , defaultImport , namedImports , namespaceLikeImport ) { const quotedModuleSpecifier = makeStringLiteral ( moduleSpecifier , quotePreference ) ; let statements ; if ( defaultImport !== undefined || namedImports ?. length ) { const topLevelTypeOnly = ( ! defaultImport || needsTypeOnly ( defaultImport ) ) && every ( namedImports , needsTypeOnly ) ; statements = combine ( statements , makeImport ( defaultImport && factory . createIdentifier ( defaultImport . name ) , namedImports ?. map ( ( { addAsTypeOnly , name } ) => factory . createImportSpecifier ( ! topLevelTypeOnly && addAsTypeOnly === AddAsTypeOnly . Required , undefined , factory . createIdentifier ( name ) ) ) , moduleSpecifier , quotePreference , topLevelTypeOnly ) ) ; } if ( namespaceLikeImport ) { const declaration = namespaceLikeImport . importKind === ImportKind . CommonJS ? factory . createImportEqualsDeclaration ( undefined , undefined , needsTypeOnly ( namespaceLikeImport ) , factory . createIdentifier ( namespaceLikeImport . name ) , factory . createExternalModuleReference ( quotedModuleSpecifier ) ) : factory . createImportDeclaration ( undefined , undefined , factory . createImportClause ( needsTypeOnly ( namespaceLikeImport ) , undefined , factory . createNamespaceImport ( factory . createIdentifier ( namespaceLikeImport . name ) ) ) , quotedModuleSpecifier , undefined ) ; statements = combine ( statements , declaration ) ; } return Debug . checkDefined ( statements ) ; } function getNewRequires ( moduleSpecifier , quotePreference , defaultImport , namedImports , namespaceLikeImport ) { const quotedModuleSpecifier = makeStringLiteral ( moduleSpecifier , quotePreference ) ; let statements ; if ( defaultImport || namedImports ?. length ) { const bindingElements = namedImports ?. map ( ( { name } ) => factory . createBindingElement ( undefined , undefined , name ) ) || [ ] ; if ( defaultImport ) { bindingElements . unshift ( factory . createBindingElement ( undefined , "default" , defaultImport . name ) ) ; } const declaration = createConstEqualsRequireDeclaration ( factory . createObjectBindingPattern ( bindingElements ) , quotedModuleSpecifier ) ; statements = combine ( statements , declaration ) ; } if ( namespaceLikeImport ) { const declaration = createConstEqualsRequireDeclaration ( namespaceLikeImport . name , quotedModuleSpecifier ) ; statements = combine ( statements , declaration ) ; } return Debug . checkDefined ( statements ) ; } function createConstEqualsRequireDeclaration ( name , quotedModuleSpecifier ) { return factory . createVariableStatement ( undefined , factory . createVariableDeclarationList ( [ factory . createVariableDeclaration ( typeof name === "string" ? factory . createIdentifier ( name ) : name , undefined , undefined , factory . createCallExpression ( factory . createIdentifier ( "require" ) , undefined , [ quotedModuleSpecifier ] ) ) ] , NodeFlags . Const ) ) as RequireVariableStatement ; } function symbolHasMeaning ( { declarations } , meaning ) { return some ( declarations , decl => ! ! ( getMeaningFromDeclaration ( decl ) & meaning ) ) ; } export function moduleSymbolToValidIdentifier ( moduleSymbol , target ) { return moduleSpecifierToValidIdentifier ( removeFileExtension ( stripQuotes ( moduleSymbol . name ) ) , target ) ; } export function moduleSpecifierToValidIdentifier ( moduleSpecifier , target ) { const baseName = getBaseFileName ( removeSuffix ( moduleSpecifier , "/index" ) ) ; let res = "" ; let lastCharWasValid = true ; const firstCharCode = baseName . charCodeAt ( 0 ) ; if ( isIdentifierStart ( firstCharCode , target ) ) { res += String . fromCharCode ( firstCharCode ) ; } else { lastCharWasValid = false ; } for ( let i = 1 ; i < baseName . length ; i ++ ) { const ch = baseName . charCodeAt ( i ) ; const isValid = isIdentifierPart ( ch , target ) ; if ( isValid ) { let char = String . fromCharCode ( ch ) ; if ( ! lastCharWasValid ) { char = char . toUpperCase ( ) ; } res += char ; } lastCharWasValid = isValid ; } return ! isStringANonContextualKeyword ( res ) ? res || "_" : `_${ res }` ; } }