namespace ts . server { export enum ProjectKind { Inferred , Configured , External , AutoImportProvider } export type Mutable < T > = { - readonly [ K in keyof T ] : T [ K ] ; } ; export function countEachFileTypes ( infos , includeSizes = false ) { const result = { js : 0 , jsSize : 0 , jsx : 0 , jsxSize : 0 , ts : 0 , tsSize : 0 , tsx : 0 , tsxSize : 0 , dts : 0 , dtsSize : 0 , deferred : 0 , deferredSize : 0 , } ; for ( const info of infos ) { const fileSize = includeSizes ? info . getTelemetryFileSize ( ) : 0 ; switch ( info . scriptKind ) { case ScriptKind . JS : result . js += 1 ; result . jsSize ! += fileSize ; break ; case ScriptKind . JSX : result . jsx += 1 ; result . jsxSize ! += fileSize ; break ; case ScriptKind . TS : if ( fileExtensionIs ( info . fileName , Extension . Dts ) ) { result . dts += 1 ; result . dtsSize ! += fileSize ; } else { result . ts += 1 ; result . tsSize ! += fileSize ; } break ; case ScriptKind . TSX : result . tsx += 1 ; result . tsxSize ! += fileSize ; break ; case ScriptKind . Deferred : result . deferred += 1 ; result . deferredSize ! += fileSize ; break ; } } return result ; } function hasOneOrMoreJsAndNoTsFiles ( project ) { const counts = countEachFileTypes ( project . getScriptInfos ( ) ) ; return counts . js > 0 && counts . ts === 0 && counts . tsx === 0 ; } export function allRootFilesAreJsOrDts ( project ) { const counts = countEachFileTypes ( project . getRootScriptInfos ( ) ) ; return counts . ts === 0 && counts . tsx === 0 ; } export function allFilesAreJsOrDts ( project ) { const counts = countEachFileTypes ( project . getScriptInfos ( ) ) ; return counts . ts === 0 && counts . tsx === 0 ; } export function hasNoTypeScriptSource ( fileNames ) { return ! fileNames . some ( fileName => ( fileExtensionIs ( fileName , Extension . Ts ) && ! fileExtensionIs ( fileName , Extension . Dts ) ) || fileExtensionIs ( fileName , Extension . Tsx ) ) ; } export interface ProjectFilesWithTSDiagnostics extends protocol . ProjectFiles { projectErrors : readonly Diagnostic [ ] ; } export interface PluginCreateInfo { project : Project ; languageService : LanguageService ; languageServiceHost : LanguageServiceHost ; serverHost : ServerHost ; session ? : Session < unknown > ; config : any ; } export interface PluginModule { create ( createInfo ) : LanguageService ; getExternalFiles ? ( proj ) : string [ ] ; onConfigurationChanged ? ( config ) : void ; } export interface PluginModuleWithName { name : string ; module : PluginModule ; } export type PluginModuleFactory = ( mod : { typescript : typeof ts ; } ) => PluginModule ; /**
     * The project root can be script info - if root is present,
     * or it could be just normalized path if root wasn't present on the host(only for non inferred project)
     */ export interface ProjectRootFile { fileName : NormalizedPath ; info ? : ScriptInfo ; } interface GeneratedFileWatcher { generatedFilePath : Path ; watcher : FileWatcher ; } type GeneratedFileWatcherMap = GeneratedFileWatcher | ESMap < Path , GeneratedFileWatcher > ; function isGeneratedFileWatcher ( watch ) { return ( watch as GeneratedFileWatcher ) . generatedFilePath !== undefined ; } export interface EmitResult { emitSkipped : boolean ; diagnostics : readonly Diagnostic [ ] ; } export abstract class Project implements LanguageServiceHost , ModuleResolutionHost { private rootFiles : ScriptInfo [ ] = [ ] ; private rootFilesMap = new Map < string , ProjectRootFile > ( ) ; private program : Program | undefined ; private externalFiles : SortedReadonlyArray < string > | undefined ; private missingFilesMap : ESMap < Path , FileWatcher > | undefined ; private generatedFilesMap : GeneratedFileWatcherMap | undefined ; private plugins : PluginModuleWithName [ ] = [ ] ; /**
         * This is map from files to unresolved imports in it
         * Maop does not contain entries for files that do not have unresolved imports
         * This helps in containing the set of files to invalidate
         */ cachedUnresolvedImportsPerFile = new Map < Path , readonly string [ ] > ( ) ; lastCachedUnresolvedImportsList : SortedReadonlyArray < string > | undefined ; private hasAddedorRemovedFiles = false ; private hasAddedOrRemovedSymlinks = false ; lastFileExceededProgramSize : string | undefined ; protected languageService : LanguageService ; public languageServiceEnabled : boolean ; readonly trace ? : ( s : string ) => void ; readonly realpath ? : ( path : string ) => string ; hasInvalidatedResolution : HasInvalidatedResolution | undefined ; resolutionCache : ResolutionCache ; private builderState : BuilderState | undefined ; /**
         * Set of files names that were updated since the last call to getChangesSinceVersion.
         */ private updatedFileNames : Set < string > | undefined ; /**
         * Set of files that was returned from the last call to getChangesSinceVersion.
         */ private lastReportedFileNames : ESMap < string , boolean > | undefined ; /**
         * Last version that was reported.
         */ private lastReportedVersion = 0 ; /**
         * Current project's program version. (incremented everytime new program is created that is not complete reuse from the old one)
         * This property is changed in 'updateGraph' based on the set of files in program
         */ private projectProgramVersion = 0 ; /**
         * Current version of the project state. It is changed when:
         * - new root file was added/removed
         * - edit happen in some file that is currently included in the project.
         * This property is different from projectStructureVersion since in most cases edits don't affect set of files in the project
         */ private projectStateVersion = 0 ; protected projectErrors : Diagnostic [ ] | undefined ; protected isInitialLoadPending : ( ) => boolean = returnFalse ; dirty = false ; typingFiles : SortedReadonlyArray < string > = emptyArray ; originalConfiguredProjects : Set < NormalizedPath > | undefined ; private packageJsonsForAutoImport : Set < string > | undefined ; getResolvedProjectReferenceToRedirect ( _fileName ) { return undefined ; } useSourceOfProjectReferenceRedirect ? ( ) ; getParsedCommandLine ? ( fileName ) ; private readonly cancellationToken : ThrottledCancellationToken ; public isNonTsProject ( ) { updateProjectIfDirty ( this ) ; return allFilesAreJsOrDts ( this ) ; } public isJsOnlyProject ( ) { updateProjectIfDirty ( this ) ; return hasOneOrMoreJsAndNoTsFiles ( this ) ; } public static resolveModule ( moduleName , initialDir , host , log , logErrors ? ) { const resolvedPath = normalizeSlashes ( host . resolvePath ( combinePaths ( initialDir , "node_modules" ) ) ) ; log ( `Loading ${ moduleName } from ${ initialDir } (resolved to ${ resolvedPath })` ) ; const result = host . require ! ( resolvedPath , moduleName ) ; if ( result . error ) { const err = result . error . stack || result . error . message || JSON . stringify ( result . error ) ; ( logErrors || log ) ( `Failed to load module '${ moduleName }' from ${ resolvedPath }: ${ err }` ) ; return undefined ; } return result . module ; } readonly currentDirectory : string ; public directoryStructureHost : DirectoryStructureHost ; public readonly getCanonicalFileName : GetCanonicalFileName ; private exportMapCache : ExportInfoMap | undefined ; private changedFilesForExportMapCache : Set < Path > | undefined ; private moduleSpecifierCache = createModuleSpecifierCache ( this ) ; private symlinks : SymlinkCache | undefined ; autoImportProviderHost : AutoImportProviderProject | false | undefined ; protected typeAcquisition : TypeAcquisition | undefined ; constructor ( readonly projectName , readonly projectKind , readonly projectService , private documentRegistry , hasExplicitListOfFiles , lastFileExceededProgramSize , private compilerOptions , public compileOnSaveEnabled , protected watchOptions , directoryStructureHost , currentDirectory ) { this . directoryStructureHost = directoryStructureHost ; this . currentDirectory = this . projectService . getNormalizedAbsolutePath ( currentDirectory || "" ) ; this . getCanonicalFileName = this . projectService . toCanonicalFileName ; this . cancellationToken = new ThrottledCancellationToken ( this . projectService . cancellationToken , this . projectService . throttleWaitMilliseconds ) ; if ( ! this . compilerOptions ) { this . compilerOptions = getDefaultCompilerOptions ( ) ; this . compilerOptions . allowNonTsExtensions = true ; this . compilerOptions . allowJs = true ; } else if ( hasExplicitListOfFiles || getAllowJSCompilerOption ( this . compilerOptions ) || this . projectService . hasDeferredExtension ( ) ) { this . compilerOptions . allowNonTsExtensions = true ; } switch ( projectService . serverMode ) { case LanguageServiceMode . Semantic : this . languageServiceEnabled = true ; break ; case LanguageServiceMode . PartialSemantic : this . languageServiceEnabled = true ; this . compilerOptions . noResolve = true ; this . compilerOptions . types = [ ] ; break ; case LanguageServiceMode . Syntactic : this . languageServiceEnabled = false ; this . compilerOptions . noResolve = true ; this . compilerOptions . types = [ ] ; break ; default : Debug . assertNever ( projectService . serverMode ) ; } this . setInternalCompilerOptionsForEmittingJsFiles ( ) ; const host = this . projectService . host ; if ( this . projectService . logger . loggingEnabled ( ) ) { this . trace = s => this . writeLog ( s ) ; } else if ( host . trace ) { this . trace = s => host . trace ! ( s ) ; } this . realpath = maybeBind ( host , host . realpath ) ; this . resolutionCache = createResolutionCache ( this , currentDirectory && this . currentDirectory , true ) ; this . languageService = createLanguageService ( this , this . documentRegistry , this . projectService . serverMode ) ; if ( lastFileExceededProgramSize ) { this . disableLanguageService ( lastFileExceededProgramSize ) ; } this . markAsDirty ( ) ; if ( projectKind !== ProjectKind . AutoImportProvider ) { this . projectService . pendingEnsureProjectForOpenFiles = true ; } } isKnownTypesPackageName ( name ) { return this . typingsCache . isKnownTypesPackageName ( name ) ; } installPackage ( options ) { return this . typingsCache . installPackage ( { ... options , projectName : this . projectName , projectRootPath : this . toPath ( this . currentDirectory ) } ) ; } getGlobalTypingsCacheLocation ( ) { return this . getGlobalCache ( ) ; } private get typingsCache ( ) : TypingsCache { return this . projectService . typingsCache ; } getSymlinkCache ( ) { if ( ! this . symlinks ) { this . symlinks = createSymlinkCache ( this . getCurrentDirectory ( ) , this . getCanonicalFileName ) ; } if ( this . program && ! this . symlinks . hasProcessedResolutions ( ) ) { this . symlinks . setSymlinksFromResolutions ( this . program . getSourceFiles ( ) , this . program . getResolvedTypeReferenceDirectives ( ) ) ; } return this . symlinks ; } getCompilationSettings ( ) { return this . compilerOptions ; } getCompilerOptions ( ) { return this . getCompilationSettings ( ) ; } getNewLine ( ) { return this . projectService . host . newLine ; } getProjectVersion ( ) { return this . projectStateVersion . toString ( ) ; } getProjectReferences ( ) { return undefined ; } getScriptFileNames ( ) { if ( ! this . rootFiles ) { return ts . emptyArray ; } let result ; this . rootFilesMap . forEach ( value => { if ( this . languageServiceEnabled || ( value . info && value . info . isScriptOpen ( ) ) ) { ( result || ( result = [ ] ) ) . push ( value . fileName ) ; } } ) ; return addRange ( result , this . typingFiles ) || ts . emptyArray ; } private getOrCreateScriptInfoAndAttachToProject ( fileName ) { const scriptInfo = this . projectService . getOrCreateScriptInfoNotOpenedByClient ( fileName , this . currentDirectory , this . directoryStructureHost ) ; if ( scriptInfo ) { const existingValue = this . rootFilesMap . get ( scriptInfo . path ) ; if ( existingValue && existingValue . info !== scriptInfo ) { this . rootFiles . push ( scriptInfo ) ; existingValue . info = scriptInfo ; } scriptInfo . attachToProject ( this ) ; } return scriptInfo ; } getScriptKind ( fileName ) { const info = this . getOrCreateScriptInfoAndAttachToProject ( fileName ) ; return ( info && info . scriptKind ) ! ; } getScriptVersion ( filename ) { const info = this . projectService . getOrCreateScriptInfoNotOpenedByClient ( filename , this . currentDirectory , this . directoryStructureHost ) ; return ( info && info . getLatestVersion ( ) ) ! ; } getScriptSnapshot ( filename ) { const scriptInfo = this . getOrCreateScriptInfoAndAttachToProject ( filename ) ; if ( scriptInfo ) { return scriptInfo . getSnapshot ( ) ; } } getCancellationToken ( ) { return this . cancellationToken ; } getCurrentDirectory ( ) { return this . currentDirectory ; } getDefaultLibFileName ( ) { const nodeModuleBinDir = getDirectoryPath ( normalizePath ( this . projectService . getExecutingFilePath ( ) ) ) ; return combinePaths ( nodeModuleBinDir , getDefaultLibFileName ( this . compilerOptions ) ) ; } useCaseSensitiveFileNames ( ) { return this . projectService . host . useCaseSensitiveFileNames ; } readDirectory ( path , extensions ? , exclude ? , include ? , depth ? ) { return this . directoryStructureHost . readDirectory ! ( path , extensions , exclude , include , depth ) ; } readFile ( fileName ) { return this . projectService . host . readFile ( fileName ) ; } writeFile ( fileName , content ) { return this . projectService . host . writeFile ( fileName , content ) ; } fileExists ( file ) { const path = this . toPath ( file ) ; return ! this . isWatchedMissingFile ( path ) && this . directoryStructureHost . fileExists ( file ) ; } resolveModuleNames ( moduleNames , containingFile , reusedNames ? , redirectedReference ? , _options ? , containingSourceFile ? ) { return this . resolutionCache . resolveModuleNames ( moduleNames , containingFile , reusedNames , redirectedReference , containingSourceFile ) ; } getResolvedModuleWithFailedLookupLocationsFromCache ( moduleName , containingFile , resolutionMode ? ) { return this . resolutionCache . getResolvedModuleWithFailedLookupLocationsFromCache ( moduleName , containingFile , resolutionMode ) ; } resolveTypeReferenceDirectives ( typeDirectiveNames , containingFile , redirectedReference ? ) { return this . resolutionCache . resolveTypeReferenceDirectives ( typeDirectiveNames , containingFile , redirectedReference ) ; } directoryExists ( path ) { return this . directoryStructureHost . directoryExists ! ( path ) ; } getDirectories ( path ) { return this . directoryStructureHost . getDirectories ! ( path ) ; } getCachedDirectoryStructureHost ( ) { return undefined ! ; } toPath ( fileName ) { return toPath ( fileName , this . currentDirectory , this . projectService . toCanonicalFileName ) ; } watchDirectoryOfFailedLookupLocation ( directory , cb , flags ) { return this . projectService . watchFactory . watchDirectory ( directory , cb , flags , this . projectService . getWatchOptions ( this ) , WatchType . FailedLookupLocations , this ) ; } clearInvalidateResolutionOfFailedLookupTimer ( ) { return this . projectService . throttledOperations . cancel ( `${ this . getProjectName ( ) }FailedLookupInvalidation` ) ; } scheduleInvalidateResolutionsOfFailedLookupLocations ( ) { this . projectService . throttledOperations . schedule ( `${ this . getProjectName ( ) }FailedLookupInvalidation` , 1000 , ( ) => { if ( this . resolutionCache . invalidateResolutionsOfFailedLookupLocations ( ) ) { this . projectService . delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles ( this ) ; } } ) ; } invalidateResolutionsOfFailedLookupLocations ( ) { if ( this . clearInvalidateResolutionOfFailedLookupTimer ( ) && this . resolutionCache . invalidateResolutionsOfFailedLookupLocations ( ) ) { this . markAsDirty ( ) ; this . projectService . delayEnsureProjectForOpenFiles ( ) ; } } onInvalidatedResolution ( ) { this . projectService . delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles ( this ) ; } watchTypeRootsDirectory ( directory , cb , flags ) { return this . projectService . watchFactory . watchDirectory ( directory , cb , flags , this . projectService . getWatchOptions ( this ) , WatchType . TypeRoots , this ) ; } hasChangedAutomaticTypeDirectiveNames ( ) { return this . resolutionCache . hasChangedAutomaticTypeDirectiveNames ( ) ; } onChangedAutomaticTypeDirectiveNames ( ) { this . projectService . delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles ( this ) ; } getGlobalCache ( ) { return this . getTypeAcquisition ( ) . enable ? this . projectService . typingsInstaller . globalTypingsCacheLocation : undefined ; } globalCacheResolutionModuleName = JsTyping . nonRelativeModuleNameForTypingCache ; fileIsOpen ( filePath ) { return this . projectService . openFiles . has ( filePath ) ; } writeLog ( s ) { this . projectService . logger . info ( s ) ; } log ( s ) { this . writeLog ( s ) ; } error ( s ) { this . projectService . logger . msg ( s , Msg . Err ) ; } private setInternalCompilerOptionsForEmittingJsFiles ( ) { if ( this . projectKind === ProjectKind . Inferred || this . projectKind === ProjectKind . External ) { this . compilerOptions . noEmitForJsFiles = true ; } } /**
         * Get the errors that dont have any file name associated
         */ getGlobalProjectErrors ( ) { return filter ( this . projectErrors , diagnostic => ! diagnostic . file ) || emptyArray ; } /**
         * Get all the project errors
         */ getAllProjectErrors ( ) { return this . projectErrors || emptyArray ; } setProjectErrors ( projectErrors ) { this . projectErrors = projectErrors ; } getLanguageService ( ensureSynchronized = true ) { if ( ensureSynchronized ) { updateProjectIfDirty ( this ) ; } return this . languageService ; } internal getSourceMapper ( ) { return this . getLanguageService ( ) . getSourceMapper ( ) ; } internal clearSourceMapperCache ( ) { this . languageService . clearSourceMapperCache ( ) ; } getDocumentPositionMapper ( generatedFileName , sourceFileName ? ) { return this . projectService . getDocumentPositionMapper ( this , generatedFileName , sourceFileName ) ; } getSourceFileLike ( fileName ) { return this . projectService . getSourceFileLike ( fileName , this ) ; } shouldEmitFile ( scriptInfo ) { return scriptInfo && ! scriptInfo . isDynamicOrHasMixedContent ( ) && ! this . program ! . isSourceOfProjectReferenceRedirect ( scriptInfo . path ) ; } getCompileOnSaveAffectedFileList ( scriptInfo ) { if ( ! this . languageServiceEnabled ) { return [ ] ; } updateProjectIfDirty ( this ) ; this . builderState = BuilderState . create ( this . program ! , this . projectService . toCanonicalFileName , this . builderState , true ) ; return mapDefined ( BuilderState . getFilesAffectedBy ( this . builderState , this . program ! , scriptInfo . path , this . cancellationToken , maybeBind ( this . projectService . host , this . projectService . host . createHash ) ) , sourceFile => this . shouldEmitFile ( this . projectService . getScriptInfoForPath ( sourceFile . path ) ) ? sourceFile . fileName : undefined ) ; } /**
         * Returns true if emit was conducted
         */ emitFile ( scriptInfo , writeFile ) { if ( ! this . languageServiceEnabled || ! this . shouldEmitFile ( scriptInfo ) ) { return { emitSkipped : true , diagnostics : emptyArray } ; } const { emitSkipped , diagnostics , outputFiles } = this . getLanguageService ( ) . getEmitOutput ( scriptInfo . fileName ) ; if ( ! emitSkipped ) { for ( const outputFile of outputFiles ) { const outputFileAbsoluteFileName = getNormalizedAbsolutePath ( outputFile . name , this . currentDirectory ) ; writeFile ( outputFileAbsoluteFileName , outputFile . text , outputFile . writeByteOrderMark ) ; } if ( this . builderState && getEmitDeclarations ( this . compilerOptions ) ) { const dtsFiles = outputFiles . filter ( f => fileExtensionIs ( f . name , Extension . Dts ) ) ; if ( dtsFiles . length === 1 ) { const sourceFile = this . program ! . getSourceFile ( scriptInfo . fileName ) ! ; const signature = this . projectService . host . createHash ? this . projectService . host . createHash ( dtsFiles [ 0 ] . text ) : generateDjb2Hash ( dtsFiles [ 0 ] . text ) ; BuilderState . updateSignatureOfFile ( this . builderState , signature , sourceFile . resolvedPath ) ; } } } return { emitSkipped , diagnostics } ; } enableLanguageService ( ) { if ( this . languageServiceEnabled || this . projectService . serverMode === LanguageServiceMode . Syntactic ) { return ; } this . languageServiceEnabled = true ; this . lastFileExceededProgramSize = undefined ; this . projectService . onUpdateLanguageServiceStateForProject ( this , true ) ; } disableLanguageService ( lastFileExceededProgramSize ? ) { if ( ! this . languageServiceEnabled ) { return ; } Debug . assert ( this . projectService . serverMode !== LanguageServiceMode . Syntactic ) ; this . languageService . cleanupSemanticCache ( ) ; this . languageServiceEnabled = false ; this . lastFileExceededProgramSize = lastFileExceededProgramSize ; this . builderState = undefined ; if ( this . autoImportProviderHost ) { this . autoImportProviderHost . close ( ) ; } this . autoImportProviderHost = undefined ; this . resolutionCache . closeTypeRootsWatch ( ) ; this . clearGeneratedFileWatch ( ) ; this . projectService . onUpdateLanguageServiceStateForProject ( this , false ) ; } getProjectName ( ) { return this . projectName ; } protected removeLocalTypingsFromTypeAcquisition ( newTypeAcquisition ) { if ( ! newTypeAcquisition || ! newTypeAcquisition . include ) { return newTypeAcquisition ; } return { ... newTypeAcquisition , include : this . removeExistingTypings ( newTypeAcquisition . include ) } ; } getExternalFiles ( ) { return sort ( flatMap ( this . plugins , plugin => { if ( typeof plugin . module . getExternalFiles !== "function" ) return ; try { return plugin . module . getExternalFiles ( this ) ; } catch ( e ) { this . projectService . logger . info ( `A plugin threw an exception in getExternalFiles: ${ e }` ) ; if ( e . stack ) { this . projectService . logger . info ( e . stack ) ; } } } ) ) ; } getSourceFile ( path ) { if ( ! this . program ) { return undefined ; } return this . program . getSourceFileByPath ( path ) ; } getSourceFileOrConfigFile ( path ) { const options = this . program ! . getCompilerOptions ( ) ; return path === options . configFilePath ? options . configFile : this . getSourceFile ( path ) ; } close ( ) { if ( this . program ) { for ( const f of this . program . getSourceFiles ( ) ) { this . detachScriptInfoIfNotRoot ( f . fileName ) ; } this . program . forEachResolvedProjectReference ( ref => this . detachScriptInfoFromProject ( ref . sourceFile . fileName ) ) ; } forEach ( this . externalFiles , externalFile => this . detachScriptInfoIfNotRoot ( externalFile ) ) ; for ( const root of this . rootFiles ) { root . detachFromProject ( this ) ; } this . projectService . pendingEnsureProjectForOpenFiles = true ; this . rootFiles = undefined ! ; this . rootFilesMap = undefined ! ; this . externalFiles = undefined ; this . program = undefined ; this . builderState = undefined ; this . resolutionCache . clear ( ) ; this . resolutionCache = undefined ! ; this . cachedUnresolvedImportsPerFile = undefined ! ; this . moduleSpecifierCache = undefined ! ; this . directoryStructureHost = undefined ! ; this . exportMapCache = undefined ; this . projectErrors = undefined ; if ( this . missingFilesMap ) { clearMap ( this . missingFilesMap , closeFileWatcher ) ; this . missingFilesMap = undefined ; } this . clearGeneratedFileWatch ( ) ; this . clearInvalidateResolutionOfFailedLookupTimer ( ) ; if ( this . autoImportProviderHost ) { this . autoImportProviderHost . close ( ) ; } this . autoImportProviderHost = undefined ; this . languageService . dispose ( ) ; this . languageService = undefined ! ; } private detachScriptInfoIfNotRoot ( uncheckedFilename ) { const info = this . projectService . getScriptInfo ( uncheckedFilename ) ; if ( info && ! this . isRoot ( info ) ) { info . detachFromProject ( this ) ; } } isClosed ( ) { return this . rootFiles === undefined ; } hasRoots ( ) { return this . rootFiles && this . rootFiles . length > 0 ; } isOrphan ( ) { return false ; } getRootFiles ( ) { return this . rootFiles && this . rootFiles . map ( info => info . fileName ) ; } getRootFilesMap ( ) { return this . rootFilesMap ; } getRootScriptInfos ( ) { return this . rootFiles ; } getScriptInfos ( ) { if ( ! this . languageServiceEnabled ) { return this . rootFiles ; } return map ( this . program ! . getSourceFiles ( ) , sourceFile => { const scriptInfo = this . projectService . getScriptInfoForPath ( sourceFile . resolvedPath ) ; Debug . assert ( ! ! scriptInfo , "getScriptInfo" , ( ) => `scriptInfo for a file '${ sourceFile . fileName }' Path: '${ sourceFile . path }' / '${ sourceFile . resolvedPath }' is missing.` ) ; return scriptInfo ; } ) ; } getExcludedFiles ( ) { return emptyArray ; } getFileNames ( excludeFilesFromExternalLibraries ? , excludeConfigFiles ? ) { if ( ! this . program ) { return [ ] ; } if ( ! this . languageServiceEnabled ) { let rootFiles = this . getRootFiles ( ) ; if ( this . compilerOptions ) { const defaultLibrary = getDefaultLibFilePath ( this . compilerOptions ) ; if ( defaultLibrary ) { ( rootFiles || ( rootFiles = [ ] ) ) . push ( asNormalizedPath ( defaultLibrary ) ) ; } } return rootFiles ; } const result = [ ] ; for ( const f of this . program . getSourceFiles ( ) ) { if ( excludeFilesFromExternalLibraries && this . program . isSourceFileFromExternalLibrary ( f ) ) { continue ; } result . push ( asNormalizedPath ( f . fileName ) ) ; } if ( ! excludeConfigFiles ) { const configFile = this . program . getCompilerOptions ( ) . configFile ; if ( configFile ) { result . push ( asNormalizedPath ( configFile . fileName ) ) ; if ( configFile . extendedSourceFiles ) { for ( const f of configFile . extendedSourceFiles ) { result . push ( asNormalizedPath ( f ) ) ; } } } } return result ; } getFileNamesWithRedirectInfo ( includeProjectReferenceRedirectInfo ) { return this . getFileNames ( ) . map ( ( fileName ) : protocol . FileWithProjectReferenceRedirectInfo => ( { fileName , isSourceOfProjectReferenceRedirect : includeProjectReferenceRedirectInfo && this . isSourceOfProjectReferenceRedirect ( fileName ) } ) ) ; } hasConfigFile ( configFilePath ) { if ( this . program && this . languageServiceEnabled ) { const configFile = this . program . getCompilerOptions ( ) . configFile ; if ( configFile ) { if ( configFilePath === asNormalizedPath ( configFile . fileName ) ) { return true ; } if ( configFile . extendedSourceFiles ) { for ( const f of configFile . extendedSourceFiles ) { if ( configFilePath === asNormalizedPath ( f ) ) { return true ; } } } } } return false ; } containsScriptInfo ( info ) { if ( this . isRoot ( info ) ) return true ; if ( ! this . program ) return false ; const file = this . program . getSourceFileByPath ( info . path ) ; return ! ! file && file . resolvedPath === info . path ; } containsFile ( filename , requireOpen ? ) { const info = this . projectService . getScriptInfoForNormalizedPath ( filename ) ; if ( info && ( info . isScriptOpen ( ) || ! requireOpen ) ) { return this . containsScriptInfo ( info ) ; } return false ; } isRoot ( info ) { return this . rootFilesMap && this . rootFilesMap . get ( info . path ) ?. info === info ; } addRoot ( info , fileName ? ) { Debug . assert ( ! this . isRoot ( info ) ) ; this . rootFiles . push ( info ) ; this . rootFilesMap . set ( info . path , { fileName : fileName || info . fileName , info } ) ; info . attachToProject ( this ) ; this . markAsDirty ( ) ; } addMissingFileRoot ( fileName ) { const path = this . projectService . toPath ( fileName ) ; this . rootFilesMap . set ( path , { fileName } ) ; this . markAsDirty ( ) ; } removeFile ( info , fileExists , detachFromProject ) { if ( this . isRoot ( info ) ) { this . removeRoot ( info ) ; } if ( fileExists ) { this . resolutionCache . removeResolutionsOfFile ( info . path ) ; } else { this . resolutionCache . invalidateResolutionOfFile ( info . path ) ; } this . cachedUnresolvedImportsPerFile . delete ( info . path ) ; if ( detachFromProject ) { info . detachFromProject ( this ) ; } this . markAsDirty ( ) ; } registerFileUpdate ( fileName ) { ( this . updatedFileNames || ( this . updatedFileNames = new Set < string > ( ) ) ) . add ( fileName ) ; } markFileAsDirty ( changedFile ) { this . markAsDirty ( ) ; if ( this . exportMapCache && ! this . exportMapCache . isEmpty ( ) ) { ( this . changedFilesForExportMapCache ||= new Set ( ) ) . add ( changedFile ) ; } } markAsDirty ( ) { if ( ! this . dirty ) { this . projectStateVersion ++ ; this . dirty = true ; } } onAutoImportProviderSettingsChanged ( ) { if ( this . autoImportProviderHost === false ) { this . autoImportProviderHost = undefined ; } else { this . autoImportProviderHost ?. markAsDirty ( ) ; } } onPackageJsonChange ( packageJsonPath ) { if ( this . packageJsonsForAutoImport ?. has ( packageJsonPath ) ) { this . moduleSpecifierCache . clear ( ) ; if ( this . autoImportProviderHost ) { this . autoImportProviderHost . markAsDirty ( ) ; } } } onFileAddedOrRemoved ( isSymlink ) { this . hasAddedorRemovedFiles = true ; if ( isSymlink ) { this . hasAddedOrRemovedSymlinks = true ; } } onDiscoveredSymlink ( ) { this . hasAddedOrRemovedSymlinks = true ; } returns updateGraph ( ) { perfLogger . logStartUpdateGraph ( ) ; this . resolutionCache . startRecordingFilesWithChangedResolutions ( ) ; const hasNewProgram = this . updateGraphWorker ( ) ; const hasAddedorRemovedFiles = this . hasAddedorRemovedFiles ; this . hasAddedorRemovedFiles = false ; this . hasAddedOrRemovedSymlinks = false ; const changedFiles = this . resolutionCache . finishRecordingFilesWithChangedResolutions ( ) || emptyArray ; for ( const file of changedFiles ) { this . cachedUnresolvedImportsPerFile . delete ( file ) ; } if ( this . languageServiceEnabled && this . projectService . serverMode === LanguageServiceMode . Semantic ) { if ( hasNewProgram || changedFiles . length ) { this . lastCachedUnresolvedImportsList = getUnresolvedImports ( this . program ! , this . cachedUnresolvedImportsPerFile ) ; } this . projectService . typingsCache . enqueueInstallTypingsForProject ( this , this . lastCachedUnresolvedImportsList , hasAddedorRemovedFiles ) ; } else { this . lastCachedUnresolvedImportsList = undefined ; } const isFirstProgramLoad = this . projectProgramVersion === 0 && hasNewProgram ; if ( hasNewProgram ) { this . projectProgramVersion ++ ; } if ( hasAddedorRemovedFiles ) { if ( ! this . autoImportProviderHost ) this . autoImportProviderHost = undefined ; this . autoImportProviderHost ?. markAsDirty ( ) ; } if ( isFirstProgramLoad ) { this . getPackageJsonAutoImportProvider ( ) ; } perfLogger . logStopUpdateGraph ( ) ; return ! hasNewProgram ; } updateTypingFiles ( typingFiles ) { if ( enumerateInsertsAndDeletes < string , string > ( typingFiles , this . typingFiles , getStringComparer ( ! this . useCaseSensitiveFileNames ( ) ) , noop , removed => this . detachScriptInfoFromProject ( removed ) ) ) { this . typingFiles = typingFiles ; this . resolutionCache . setFilesWithInvalidatedNonRelativeUnresolvedImports ( this . cachedUnresolvedImportsPerFile ) ; this . projectService . delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles ( this ) ; } } getCurrentProgram ( ) { return this . program ; } protected removeExistingTypings ( include ) { const existing = getAutomaticTypeDirectiveNames ( this . getCompilerOptions ( ) , this . directoryStructureHost ) ; return include . filter ( i => existing . indexOf ( i ) < 0 ) ; } private updateGraphWorker ( ) { const oldProgram = this . program ; Debug . assert ( ! this . isClosed ( ) , "Called update graph worker of closed project" ) ; this . writeLog ( `Starting updateGraphWorker: Project: ${ this . getProjectName ( ) }` ) ; const start = timestamp ( ) ; this . hasInvalidatedResolution = this . resolutionCache . createHasInvalidatedResolution ( ) ; this . resolutionCache . startCachingPerDirectoryResolution ( ) ; this . program = this . languageService . getProgram ( ) ; this . dirty = false ; this . resolutionCache . finishCachingPerDirectoryResolution ( ) ; Debug . assert ( oldProgram === undefined || this . program !== undefined ) ; let hasNewProgram = false ; if ( this . program && ( ! oldProgram || ( this . program !== oldProgram && this . program . structureIsReused !== StructureIsReused . Completely ) ) ) { hasNewProgram = true ; if ( oldProgram ) { for ( const f of oldProgram . getSourceFiles ( ) ) { const newFile = this . program . getSourceFileByPath ( f . resolvedPath ) ; if ( ! newFile || ( f . resolvedPath === f . path && newFile . resolvedPath !== f . path ) ) { this . detachScriptInfoFromProject ( f . fileName , ! ! this . program . getSourceFileByPath ( f . path ) ) ; } } oldProgram . forEachResolvedProjectReference ( resolvedProjectReference => { if ( ! this . program ! . getResolvedProjectReferenceByPath ( resolvedProjectReference . sourceFile . path ) ) { this . detachScriptInfoFromProject ( resolvedProjectReference . sourceFile . fileName ) ; } } ) ; } updateMissingFilePathsWatch ( this . program , this . missingFilesMap || ( this . missingFilesMap = new Map ( ) ) , missingFilePath => this . addMissingFileWatcher ( missingFilePath ) ) ; if ( this . generatedFilesMap ) { const outPath = outFile ( this . compilerOptions ) ; if ( isGeneratedFileWatcher ( this . generatedFilesMap ) ) { if ( ! outPath || ! this . isValidGeneratedFileWatcher ( removeFileExtension ( outPath ) + Extension . Dts , this . generatedFilesMap ) ) { this . clearGeneratedFileWatch ( ) ; } } else { if ( outPath ) { this . clearGeneratedFileWatch ( ) ; } else { this . generatedFilesMap . forEach ( ( watcher , source ) => { const sourceFile = this . program ! . getSourceFileByPath ( source ) ; if ( ! sourceFile || sourceFile . resolvedPath !== source || ! this . isValidGeneratedFileWatcher ( getDeclarationEmitOutputFilePathWorker ( sourceFile . fileName , this . compilerOptions , this . currentDirectory , this . program ! . getCommonSourceDirectory ( ) , this . getCanonicalFileName ) , watcher ) ) { closeFileWatcherOf ( watcher ) ; ( this . generatedFilesMap as ESMap < string , GeneratedFileWatcher > ) . delete ( source ) ; } } ) ; } } } if ( this . languageServiceEnabled && this . projectService . serverMode === LanguageServiceMode . Semantic ) { this . resolutionCache . updateTypeRootsWatch ( ) ; } } if ( this . exportMapCache && ! this . exportMapCache . isEmpty ( ) ) { this . exportMapCache . releaseSymbols ( ) ; if ( this . hasAddedorRemovedFiles || oldProgram && ! this . program ! . structureIsReused ) { this . exportMapCache . clear ( ) ; } else if ( this . changedFilesForExportMapCache && oldProgram && this . program ) { forEachKey ( this . changedFilesForExportMapCache , fileName => { const oldSourceFile = oldProgram . getSourceFileByPath ( fileName ) ; const sourceFile = this . program ! . getSourceFileByPath ( fileName ) ; if ( ! oldSourceFile || ! sourceFile ) { this . exportMapCache ! . clear ( ) ; return true ; } return this . exportMapCache ! . onFileChanged ( oldSourceFile , sourceFile , ! ! this . getTypeAcquisition ( ) . enable ) ; } ) ; } } if ( this . changedFilesForExportMapCache ) { this . changedFilesForExportMapCache . clear ( ) ; } if ( this . hasAddedOrRemovedSymlinks || this . program && ! this . program . structureIsReused && this . getCompilerOptions ( ) . preserveSymlinks ) { this . symlinks = undefined ; this . moduleSpecifierCache . clear ( ) ; } const oldExternalFiles = this . externalFiles || emptyArray as SortedReadonlyArray < string > ; this . externalFiles = this . getExternalFiles ( ) ; enumerateInsertsAndDeletes < string , string > ( this . externalFiles , oldExternalFiles , getStringComparer ( ! this . useCaseSensitiveFileNames ( ) ) , inserted => { const scriptInfo = this . projectService . getOrCreateScriptInfoNotOpenedByClient ( inserted , this . currentDirectory , this . directoryStructureHost ) ; scriptInfo ?. attachToProject ( this ) ; } , removed => this . detachScriptInfoFromProject ( removed ) ) ; const elapsed = timestamp ( ) - start ; this . sendPerformanceEvent ( "UpdateGraph" , elapsed ) ; this . writeLog ( `Finishing updateGraphWorker: Project: ${ this . getProjectName ( ) } Version: ${ this . getProjectVersion ( ) } structureChanged: ${ hasNewProgram }${ this . program ? ` structureIsReused:: ${ ( ts as any ) . StructureIsReused [ this . program . structureIsReused ] }` : "" } Elapsed: ${ elapsed }ms` ) ; if ( this . hasAddedorRemovedFiles ) { this . print ( true ) ; } else if ( this . program !== oldProgram ) { this . writeLog ( `Different program with same set of files` ) ; } return hasNewProgram ; } sendPerformanceEvent ( kind , durationMs ) { this . projectService . sendPerformanceEvent ( kind , durationMs ) ; } private detachScriptInfoFromProject ( uncheckedFileName , noRemoveResolution ? ) { const scriptInfoToDetach = this . projectService . getScriptInfo ( uncheckedFileName ) ; if ( scriptInfoToDetach ) { scriptInfoToDetach . detachFromProject ( this ) ; if ( ! noRemoveResolution ) { this . resolutionCache . removeResolutionsOfFile ( scriptInfoToDetach . path ) ; } } } private addMissingFileWatcher ( missingFilePath ) { if ( isConfiguredProject ( this ) ) { const configFileExistenceInfo = this . projectService . configFileExistenceInfoCache . get ( missingFilePath as string as NormalizedPath ) ; if ( configFileExistenceInfo ?. config ?. projects . has ( this . canonicalConfigFilePath ) ) return noopFileWatcher ; } const fileWatcher = this . projectService . watchFactory . watchFile ( missingFilePath , ( fileName , eventKind ) => { if ( isConfiguredProject ( this ) ) { this . getCachedDirectoryStructureHost ( ) . addOrDeleteFile ( fileName , missingFilePath , eventKind ) ; } if ( eventKind === FileWatcherEventKind . Created && this . missingFilesMap ! . has ( missingFilePath ) ) { this . missingFilesMap ! . delete ( missingFilePath ) ; fileWatcher . close ( ) ; this . projectService . delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles ( this ) ; } } , PollingInterval . Medium , this . projectService . getWatchOptions ( this ) , WatchType . MissingFile , this ) ; return fileWatcher ; } private isWatchedMissingFile ( path ) { return ! ! this . missingFilesMap && this . missingFilesMap . has ( path ) ; } addGeneratedFileWatch ( generatedFile , sourceFile ) { if ( outFile ( this . compilerOptions ) ) { if ( ! this . generatedFilesMap ) { this . generatedFilesMap = this . createGeneratedFileWatcher ( generatedFile ) ; } } else { const path = this . toPath ( sourceFile ) ; if ( this . generatedFilesMap ) { if ( isGeneratedFileWatcher ( this . generatedFilesMap ) ) { Debug . fail ( `${ this . projectName } Expected to not have --out watcher for generated file with options: ${ JSON . stringify ( this . compilerOptions ) }` ) ; return ; } if ( this . generatedFilesMap . has ( path ) ) return ; } else { this . generatedFilesMap = new Map ( ) ; } this . generatedFilesMap . set ( path , this . createGeneratedFileWatcher ( generatedFile ) ) ; } } private createGeneratedFileWatcher ( generatedFile ) { return { generatedFilePath : this . toPath ( generatedFile ) , watcher : this . projectService . watchFactory . watchFile ( generatedFile , ( ) => { this . clearSourceMapperCache ( ) ; this . projectService . delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles ( this ) ; } , PollingInterval . High , this . projectService . getWatchOptions ( this ) , WatchType . MissingGeneratedFile , this ) } ; } private isValidGeneratedFileWatcher ( generateFile , watcher ) { return this . toPath ( generateFile ) === watcher . generatedFilePath ; } private clearGeneratedFileWatch ( ) { if ( this . generatedFilesMap ) { if ( isGeneratedFileWatcher ( this . generatedFilesMap ) ) { closeFileWatcherOf ( this . generatedFilesMap ) ; } else { clearMap ( this . generatedFilesMap , closeFileWatcherOf ) ; } this . generatedFilesMap = undefined ; } } getScriptInfoForNormalizedPath ( fileName ) { const scriptInfo = this . projectService . getScriptInfoForPath ( this . toPath ( fileName ) ) ; if ( scriptInfo && ! scriptInfo . isAttached ( this ) ) { return Errors . ThrowProjectDoesNotContainDocument ( fileName , this ) ; } return scriptInfo ; } getScriptInfo ( uncheckedFileName ) { return this . projectService . getScriptInfo ( uncheckedFileName ) ; } filesToString ( writeProjectFileNames ) { if ( this . isInitialLoadPending ( ) ) return "\tFiles (0) InitialLoadPending\n" ; if ( ! this . program ) return "\tFiles (0) NoProgram\n" ; const sourceFiles = this . program . getSourceFiles ( ) ; let strBuilder = `\tFiles (${ sourceFiles . length })\n` ; if ( writeProjectFileNames ) { for ( const file of sourceFiles ) { strBuilder += `\t${ file . fileName }\n` ; } strBuilder += "\n\n" ; explainFiles ( this . program , s => strBuilder += `\t${ s }\n` ) ; } return strBuilder ; } print ( writeProjectFileNames ) { this . writeLog ( `Project '${ this . projectName }' (${ ProjectKind [ this . projectKind ] })` ) ; this . writeLog ( this . filesToString ( writeProjectFileNames && this . projectService . logger . hasLevel ( LogLevel . verbose ) ) ) ; this . writeLog ( "-----------------------------------------------" ) ; if ( this . autoImportProviderHost ) { this . autoImportProviderHost . print ( false ) ; } } setCompilerOptions ( compilerOptions ) { if ( compilerOptions ) { compilerOptions . allowNonTsExtensions = true ; const oldOptions = this . compilerOptions ; this . compilerOptions = compilerOptions ; this . setInternalCompilerOptionsForEmittingJsFiles ( ) ; if ( changesAffectModuleResolution ( oldOptions , compilerOptions ) ) { this . cachedUnresolvedImportsPerFile . clear ( ) ; this . lastCachedUnresolvedImportsList = undefined ; this . resolutionCache . clear ( ) ; this . moduleSpecifierCache . clear ( ) ; } this . markAsDirty ( ) ; } } setWatchOptions ( watchOptions ) { this . watchOptions = watchOptions ; } getWatchOptions ( ) { return this . watchOptions ; } setTypeAcquisition ( newTypeAcquisition ) { if ( newTypeAcquisition ) { this . typeAcquisition = this . removeLocalTypingsFromTypeAcquisition ( newTypeAcquisition ) ; } } getTypeAcquisition ( ) { return this . typeAcquisition || { } ; } getChangesSinceVersion ( lastKnownVersion ? , includeProjectReferenceRedirectInfo ? ) { const includeProjectReferenceRedirectInfoIfRequested = includeProjectReferenceRedirectInfo ? ( files ) => arrayFrom ( files . entries ( ) , ( [ fileName , isSourceOfProjectReferenceRedirect ] ) : protocol . FileWithProjectReferenceRedirectInfo => ( { fileName , isSourceOfProjectReferenceRedirect } ) ) : ( files ) => arrayFrom ( files . keys ( ) ) ; if ( ! this . isInitialLoadPending ( ) ) { updateProjectIfDirty ( this ) ; } const info = { projectName : this . getProjectName ( ) , version : this . projectProgramVersion , isInferred : isInferredProject ( this ) , options : this . getCompilationSettings ( ) , languageServiceDisabled : ! this . languageServiceEnabled , lastFileExceededProgramSize : this . lastFileExceededProgramSize } ; const updatedFileNames = this . updatedFileNames ; this . updatedFileNames = undefined ; if ( this . lastReportedFileNames && lastKnownVersion === this . lastReportedVersion ) { if ( this . projectProgramVersion === this . lastReportedVersion && ! updatedFileNames ) { return { info , projectErrors : this . getGlobalProjectErrors ( ) } ; } const lastReportedFileNames = this . lastReportedFileNames ; const externalFiles = this . getExternalFiles ( ) . map ( ( f ) : protocol . FileWithProjectReferenceRedirectInfo => ( { fileName : toNormalizedPath ( f ) , isSourceOfProjectReferenceRedirect : false } ) ) ; const currentFiles = arrayToMap ( this . getFileNamesWithRedirectInfo ( ! ! includeProjectReferenceRedirectInfo ) . concat ( externalFiles ) , info => info . fileName , info => info . isSourceOfProjectReferenceRedirect ) ; const added = new Map < string , boolean > ( ) ; const removed = new Map < string , boolean > ( ) ; const updated = updatedFileNames ? arrayFrom ( updatedFileNames . keys ( ) ) : [ ] ; const updatedRedirects = [ ] ; forEachEntry ( currentFiles , ( isSourceOfProjectReferenceRedirect , fileName ) => { if ( ! lastReportedFileNames . has ( fileName ) ) { added . set ( fileName , isSourceOfProjectReferenceRedirect ) ; } else if ( includeProjectReferenceRedirectInfo && isSourceOfProjectReferenceRedirect !== lastReportedFileNames . get ( fileName ) ) { updatedRedirects . push ( { fileName , isSourceOfProjectReferenceRedirect } ) ; } } ) ; forEachEntry ( lastReportedFileNames , ( isSourceOfProjectReferenceRedirect , fileName ) => { if ( ! currentFiles . has ( fileName ) ) { removed . set ( fileName , isSourceOfProjectReferenceRedirect ) ; } } ) ; this . lastReportedFileNames = currentFiles ; this . lastReportedVersion = this . projectProgramVersion ; return { info , changes : { added : includeProjectReferenceRedirectInfoIfRequested ( added ) , removed : includeProjectReferenceRedirectInfoIfRequested ( removed ) , updated : includeProjectReferenceRedirectInfo ? updated . map ( ( fileName ) : protocol . FileWithProjectReferenceRedirectInfo => ( { fileName , isSourceOfProjectReferenceRedirect : this . isSourceOfProjectReferenceRedirect ( fileName ) } ) ) : updated , updatedRedirects : includeProjectReferenceRedirectInfo ? updatedRedirects : undefined } , projectErrors : this . getGlobalProjectErrors ( ) } ; } else { const projectFileNames = this . getFileNamesWithRedirectInfo ( ! ! includeProjectReferenceRedirectInfo ) ; const externalFiles = this . getExternalFiles ( ) . map ( ( f ) : protocol . FileWithProjectReferenceRedirectInfo => ( { fileName : toNormalizedPath ( f ) , isSourceOfProjectReferenceRedirect : false } ) ) ; const allFiles = projectFileNames . concat ( externalFiles ) ; this . lastReportedFileNames = arrayToMap ( allFiles , info => info . fileName , info => info . isSourceOfProjectReferenceRedirect ) ; this . lastReportedVersion = this . projectProgramVersion ; return { info , files : includeProjectReferenceRedirectInfo ? allFiles : allFiles . map ( f => f . fileName ) , projectErrors : this . getGlobalProjectErrors ( ) } ; } } protected removeRoot ( info ) { orderedRemoveItem ( this . rootFiles , info ) ; this . rootFilesMap . delete ( info . path ) ; } isSourceOfProjectReferenceRedirect ( fileName ) { return ! ! this . program && this . program . isSourceOfProjectReferenceRedirect ( fileName ) ; } protected enableGlobalPlugins ( options , pluginConfigOverrides ) { const host = this . projectService . host ; if ( ! host . require ) { this . projectService . logger . info ( "Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded" ) ; return ; } const searchPaths = [ ... this . projectService . pluginProbeLocations , combinePaths ( this . projectService . getExecutingFilePath ( ) , "../../.." ) , ] ; if ( this . projectService . globalPlugins ) { for ( const globalPluginName of this . projectService . globalPlugins ) { if ( ! globalPluginName ) continue ; if ( options . plugins && options . plugins . some ( p => p . name === globalPluginName ) ) continue ; this . projectService . logger . info ( `Loading global plugin ${ globalPluginName }` ) ; this . enablePlugin ( { name : globalPluginName , global : true } as PluginImport , searchPaths , pluginConfigOverrides ) ; } } } protected enablePlugin ( pluginConfigEntry , searchPaths , pluginConfigOverrides ) { this . projectService . logger . info ( `Enabling plugin ${ pluginConfigEntry . name } from candidate paths: ${ searchPaths . join ( "," ) }` ) ; if ( ! pluginConfigEntry . name || parsePackageName ( pluginConfigEntry . name ) . rest ) { this . projectService . logger . info ( `Skipped loading plugin ${ pluginConfigEntry . name || JSON . stringify ( pluginConfigEntry ) } because only package name is allowed plugin name` ) ; return ; } const log = ( message ) => this . projectService . logger . info ( message ) ; let errorLogs ; const logError = ( message ) => { ( errorLogs || ( errorLogs = [ ] ) ) . push ( message ) ; } ; const resolvedModule = firstDefined ( searchPaths , searchPath => Project . resolveModule ( pluginConfigEntry . name , searchPath , this . projectService . host , log , logError ) as PluginModuleFactory | undefined ) ; if ( resolvedModule ) { const configurationOverride = pluginConfigOverrides && pluginConfigOverrides . get ( pluginConfigEntry . name ) ; if ( configurationOverride ) { const pluginName = pluginConfigEntry . name ; pluginConfigEntry = configurationOverride ; pluginConfigEntry . name = pluginName ; } this . enableProxy ( resolvedModule , pluginConfigEntry ) ; } else { forEach ( errorLogs , log ) ; this . projectService . logger . info ( `Couldn't find ${ pluginConfigEntry . name }` ) ; } } private enableProxy ( pluginModuleFactory , configEntry ) { try { if ( typeof pluginModuleFactory !== "function" ) { this . projectService . logger . info ( `Skipped loading plugin ${ configEntry . name } because it did not expose a proper factory function` ) ; return ; } const info = { config : configEntry , project : this , languageService : this . languageService , languageServiceHost : this , serverHost : this . projectService . host , session : this . projectService . session } ; const pluginModule = pluginModuleFactory ( { typescript : ts } ) ; const newLS = pluginModule . create ( info ) ; for ( const k of Object . keys ( this . languageService ) ) { if ( ! ( k in newLS ) ) { this . projectService . logger . info ( `Plugin activation warning: Missing proxied method ${ k } in created LS. Patching.` ) ; ( newLS as any ) [ k ] = ( this . languageService as any ) [ k ] ; } } this . projectService . logger . info ( `Plugin validation succeeded` ) ; this . languageService = newLS ; this . plugins . push ( { name : configEntry . name , module : pluginModule } ) ; } catch ( e ) { this . projectService . logger . info ( `Plugin activation failed: ${ e }` ) ; } } onPluginConfigurationChanged ( pluginName , configuration ) { this . plugins . filter ( plugin => plugin . name === pluginName ) . forEach ( plugin => { if ( plugin . module . onConfigurationChanged ) { plugin . module . onConfigurationChanged ( configuration ) ; } } ) ; } /** Starts a new check for diagnostics. Call this if some file has updated that would cause diagnostics to be changed. */ refreshDiagnostics ( ) { this . projectService . sendProjectsUpdatedInBackgroundEvent ( ) ; } getPackageJsonsVisibleToFile ( fileName , rootDir ? ) { if ( this . projectService . serverMode !== LanguageServiceMode . Semantic ) return emptyArray ; return this . projectService . getPackageJsonsVisibleToFile ( fileName , rootDir ) ; } getNearestAncestorDirectoryWithPackageJson ( fileName ) { return this . projectService . getNearestAncestorDirectoryWithPackageJson ( fileName ) ; } getPackageJsonsForAutoImport ( rootDir ? ) { const packageJsons = this . getPackageJsonsVisibleToFile ( combinePaths ( this . currentDirectory , inferredTypesContainingFile ) , rootDir ) ; this . packageJsonsForAutoImport = new Set ( packageJsons . map ( p => p . fileName ) ) ; return packageJsons ; } getCachedExportInfoMap ( ) { return this . exportMapCache ||= createCacheableExportInfoMap ( this ) ; } clearCachedExportInfoMap ( ) { this . exportMapCache ?. clear ( ) ; } getModuleSpecifierCache ( ) { return this . moduleSpecifierCache ; } includePackageJsonAutoImports ( ) { if ( this . projectService . includePackageJsonAutoImports ( ) === PackageJsonAutoImportPreference . Off || ! this . languageServiceEnabled || isInsideNodeModules ( this . currentDirectory ) || ! this . isDefaultProjectForOpenFiles ( ) ) { return PackageJsonAutoImportPreference . Off ; } return this . projectService . includePackageJsonAutoImports ( ) ; } getModuleResolutionHostForAutoImportProvider ( ) { if ( this . program ) { return { fileExists : this . program . fileExists , directoryExists : this . program . directoryExists , realpath : this . program . realpath || this . projectService . host . realpath ?. bind ( this . projectService . host ) , getCurrentDirectory : this . getCurrentDirectory . bind ( this ) , readFile : this . projectService . host . readFile . bind ( this . projectService . host ) , getDirectories : this . projectService . host . getDirectories . bind ( this . projectService . host ) , trace : this . projectService . host . trace ?. bind ( this . projectService . host ) , useCaseSensitiveFileNames : this . program . useCaseSensitiveFileNames ( ) , } ; } return this . projectService . host ; } getPackageJsonAutoImportProvider ( ) { if ( this . autoImportProviderHost === false ) { return undefined ; } if ( this . projectService . serverMode !== LanguageServiceMode . Semantic ) { this . autoImportProviderHost = false ; return undefined ; } if ( this . autoImportProviderHost ) { updateProjectIfDirty ( this . autoImportProviderHost ) ; if ( this . autoImportProviderHost . isEmpty ( ) ) { this . autoImportProviderHost . close ( ) ; this . autoImportProviderHost = undefined ; return undefined ; } return this . autoImportProviderHost . getCurrentProgram ( ) ; } const dependencySelection = this . includePackageJsonAutoImports ( ) ; if ( dependencySelection ) { const start = timestamp ( ) ; this . autoImportProviderHost = AutoImportProviderProject . create ( dependencySelection , this , this . getModuleResolutionHostForAutoImportProvider ( ) , this . documentRegistry ) ; if ( this . autoImportProviderHost ) { updateProjectIfDirty ( this . autoImportProviderHost ) ; this . sendPerformanceEvent ( "CreatePackageJsonAutoImportProvider" , timestamp ( ) - start ) ; return this . autoImportProviderHost . getCurrentProgram ( ) ; } } } private isDefaultProjectForOpenFiles ( ) { return ! ! forEachEntry ( this . projectService . openFiles , ( _ , fileName ) => this . projectService . tryGetDefaultProjectForFile ( toNormalizedPath ( fileName ) ) === this ) ; } watchNodeModulesForPackageJsonChanges ( directoryPath ) { return this . projectService . watchPackageJsonsInNodeModules ( this . toPath ( directoryPath ) , this ) ; } getIncompleteCompletionsCache ( ) { return this . projectService . getIncompleteCompletionsCache ( ) ; } } function getUnresolvedImports ( program , cachedUnresolvedImportsPerFile ) { const ambientModules = program . getTypeChecker ( ) . getAmbientModules ( ) . map ( mod => stripQuotes ( mod . getName ( ) ) ) ; return sortAndDeduplicate ( flatMap ( program . getSourceFiles ( ) , sourceFile => extractUnresolvedImportsFromSourceFile ( sourceFile , ambientModules , cachedUnresolvedImportsPerFile ) ) ) ; } function extractUnresolvedImportsFromSourceFile ( file , ambientModules , cachedUnresolvedImportsPerFile ) { return getOrUpdate ( cachedUnresolvedImportsPerFile , file . path , ( ) => { if ( ! file . resolvedModules ) return emptyArray ; let unresolvedImports ; file . resolvedModules . forEach ( ( resolvedModule , name ) => { if ( ( ! resolvedModule || ! resolutionExtensionIsTSOrJson ( resolvedModule . extension ) ) && ! isExternalModuleNameRelative ( name ) && ! ambientModules . some ( m => m === name ) ) { unresolvedImports = append ( unresolvedImports , parsePackageName ( name ) . packageName ) ; } } ) ; return unresolvedImports || emptyArray ; } ) ; } /**
     * If a file is opened and no tsconfig (or jsconfig) is found,
     * the file and its imports/references are put into an InferredProject.
     */ export class InferredProject extends Project { private _isJsInferredProject = false ; toggleJsInferredProject ( isJsInferredProject ) { if ( isJsInferredProject !== this . _isJsInferredProject ) { this . _isJsInferredProject = isJsInferredProject ; this . setCompilerOptions ( ) ; } } setCompilerOptions ( options ? ) { if ( ! options && ! this . getCompilationSettings ( ) ) { return ; } const newOptions = cloneCompilerOptions ( options || this . getCompilationSettings ( ) ) ; if ( this . _isJsInferredProject && typeof newOptions . maxNodeModuleJsDepth !== "number" ) { newOptions . maxNodeModuleJsDepth = 2 ; } else if ( ! this . _isJsInferredProject ) { newOptions . maxNodeModuleJsDepth = undefined ; } newOptions . allowJs = true ; super . setCompilerOptions ( newOptions ) ; } /** this is canonical project root path */ readonly projectRootPath : string | undefined ; /** stored only if their is no projectRootPath and this isnt single inferred project */ readonly canonicalCurrentDirectory : string | undefined ; constructor ( projectService , documentRegistry , compilerOptions , watchOptions , projectRootPath , currentDirectory , pluginConfigOverrides , typeAcquisition ) { super ( projectService . newInferredProjectName ( ) , ProjectKind . Inferred , projectService , documentRegistry , undefined ! , undefined , compilerOptions , false , watchOptions , projectService . host , currentDirectory ) ; this . typeAcquisition = typeAcquisition ; this . projectRootPath = projectRootPath && projectService . toCanonicalFileName ( projectRootPath ) ; if ( ! projectRootPath && ! projectService . useSingleInferredProject ) { this . canonicalCurrentDirectory = projectService . toCanonicalFileName ( this . currentDirectory ) ; } this . enableGlobalPlugins ( this . getCompilerOptions ( ) , pluginConfigOverrides ) ; } addRoot ( info ) { Debug . assert ( info . isScriptOpen ( ) ) ; this . projectService . startWatchingConfigFilesForInferredProjectRoot ( info ) ; if ( ! this . _isJsInferredProject && info . isJavaScript ( ) ) { this . toggleJsInferredProject ( true ) ; } super . addRoot ( info ) ; } removeRoot ( info ) { this . projectService . stopWatchingConfigFilesForInferredProjectRoot ( info ) ; super . removeRoot ( info ) ; if ( this . _isJsInferredProject && info . isJavaScript ( ) ) { if ( every ( this . getRootScriptInfos ( ) , rootInfo => ! rootInfo . isJavaScript ( ) ) ) { this . toggleJsInferredProject ( false ) ; } } } isOrphan ( ) { return ! this . hasRoots ( ) ; } isProjectWithSingleRoot ( ) { return ( ! this . projectRootPath && ! this . projectService . useSingleInferredProject ) || this . getRootScriptInfos ( ) . length === 1 ; } close ( ) { forEach ( this . getRootScriptInfos ( ) , info => this . projectService . stopWatchingConfigFilesForInferredProjectRoot ( info ) ) ; super . close ( ) ; } getTypeAcquisition ( ) { return this . typeAcquisition || { enable : allRootFilesAreJsOrDts ( this ) , include : ts . emptyArray , exclude : ts . emptyArray } ; } } export class AutoImportProviderProject extends Project { private static readonly maxDependencies = 10 ; static getRootFileNames ( dependencySelection , hostProject , moduleResolutionHost , compilerOptions ) { if ( ! dependencySelection ) { return ts . emptyArray ; } const program = hostProject . getCurrentProgram ( ) ; if ( ! program ) { return ts . emptyArray ; } let dependencyNames ; let rootNames ; const rootFileName = combinePaths ( hostProject . currentDirectory , inferredTypesContainingFile ) ; const packageJsons = hostProject . getPackageJsonsForAutoImport ( combinePaths ( hostProject . currentDirectory , rootFileName ) ) ; for ( const packageJson of packageJsons ) { packageJson . dependencies ?. forEach ( ( _ , dependenyName ) => addDependency ( dependenyName ) ) ; packageJson . peerDependencies ?. forEach ( ( _ , dependencyName ) => addDependency ( dependencyName ) ) ; } if ( dependencyNames ) { let dependenciesAdded = 0 ; const symlinkCache = hostProject . getSymlinkCache ( ) ; for ( const name of arrayFrom ( dependencyNames . keys ( ) ) ) { if ( dependencySelection === PackageJsonAutoImportPreference . Auto && dependenciesAdded > this . maxDependencies ) { hostProject . log ( `Auto-import provider attempted to add more than ${ this . maxDependencies } dependencies.` ) ; return ts . emptyArray ; } const packageJson = resolvePackageNameToPackageJson ( name , hostProject . currentDirectory , compilerOptions , moduleResolutionHost , program . getModuleResolutionCache ( ) ) ; if ( packageJson ) { const entrypoints = getRootNamesFromPackageJson ( packageJson , program , symlinkCache ) ; if ( entrypoints ) { rootNames = concatenate ( rootNames , entrypoints ) ; dependenciesAdded += entrypoints . length ? 1 : 0 ; continue ; } } const typesPackageJson = resolvePackageNameToPackageJson ( `@types/${ name }` , hostProject . currentDirectory , compilerOptions , moduleResolutionHost , program . getModuleResolutionCache ( ) ) ; if ( typesPackageJson ) { const entrypoints = getRootNamesFromPackageJson ( typesPackageJson , program , symlinkCache ) ; rootNames = concatenate ( rootNames , entrypoints ) ; dependenciesAdded += entrypoints ?. length ? 1 : 0 ; continue ; } if ( packageJson && compilerOptions . allowJs && compilerOptions . maxNodeModuleJsDepth ) { const entrypoints = getRootNamesFromPackageJson ( packageJson , program , symlinkCache , true ) ; rootNames = concatenate ( rootNames , entrypoints ) ; dependenciesAdded += entrypoints ?. length ? 1 : 0 ; } } } return rootNames || ts . emptyArray ; function addDependency ( dependency ) { if ( ! startsWith ( dependency , "@types/" ) ) { ( dependencyNames || ( dependencyNames = new Set ( ) ) ) . add ( dependency ) ; } } type PackageJsonInfo = NonNullable < ReturnType < typeof resolvePackageNameToPackageJson > > ; function getRootNamesFromPackageJson ( packageJson , program , symlinkCache , resolveJs ? ) { const entrypoints = getEntrypointsFromPackageJsonInfo ( packageJson , compilerOptions , moduleResolutionHost , program . getModuleResolutionCache ( ) , resolveJs ) ; if ( entrypoints ) { const real = moduleResolutionHost . realpath ?. ( packageJson . packageDirectory ) ; const isSymlink = real && real !== packageJson . packageDirectory ; if ( isSymlink ) { symlinkCache . setSymlinkedDirectory ( packageJson . packageDirectory , { real , realPath : hostProject . toPath ( real ) , } ) ; } return mapDefined ( entrypoints , entrypoint => { const resolvedFileName = isSymlink ? entrypoint . replace ( packageJson . packageDirectory , real ) : entrypoint ; if ( ! program . getSourceFile ( resolvedFileName ) && ! ( isSymlink && program . getSourceFile ( entrypoint ) ) ) { return resolvedFileName ; } } ) ; } } } static readonly compilerOptionsOverrides : CompilerOptions = { diagnostics : false , skipLibCheck : true , sourceMap : false , types : ts . emptyArray , lib : ts . emptyArray , noLib : true , } ; static create ( dependencySelection , hostProject , moduleResolutionHost , documentRegistry ) { if ( dependencySelection === PackageJsonAutoImportPreference . Off ) { return undefined ; } const compilerOptions = { ... hostProject . getCompilerOptions ( ) , ... this . compilerOptionsOverrides , } ; const rootNames = this . getRootFileNames ( dependencySelection , hostProject , moduleResolutionHost , compilerOptions ) ; if ( ! rootNames . length ) { return undefined ; } return new AutoImportProviderProject ( hostProject , rootNames , documentRegistry , compilerOptions ) ; } private rootFileNames : string [ ] | undefined ; constructor ( private hostProject , initialRootNames , documentRegistry , compilerOptions ) { super ( hostProject . projectService . newAutoImportProviderProjectName ( ) , ProjectKind . AutoImportProvider , hostProject . projectService , documentRegistry , false , undefined , compilerOptions , false , hostProject . getWatchOptions ( ) , hostProject . projectService . host , hostProject . currentDirectory ) ; this . rootFileNames = initialRootNames ; this . useSourceOfProjectReferenceRedirect = maybeBind ( this . hostProject , this . hostProject . useSourceOfProjectReferenceRedirect ) ; this . getParsedCommandLine = maybeBind ( this . hostProject , this . hostProject . getParsedCommandLine ) ; } isEmpty ( ) { return ! some ( this . rootFileNames ) ; } isOrphan ( ) { return true ; } updateGraph ( ) { let rootFileNames = this . rootFileNames ; if ( ! rootFileNames ) { rootFileNames = AutoImportProviderProject . getRootFileNames ( this . hostProject . includePackageJsonAutoImports ( ) , this . hostProject , this . hostProject . getModuleResolutionHostForAutoImportProvider ( ) , this . getCompilationSettings ( ) ) ; } this . projectService . setFileNamesOfAutoImportProviderProject ( this , rootFileNames ) ; this . rootFileNames = rootFileNames ; const oldProgram = this . getCurrentProgram ( ) ; const hasSameSetOfFiles = super . updateGraph ( ) ; if ( oldProgram && oldProgram !== this . getCurrentProgram ( ) ) { this . hostProject . clearCachedExportInfoMap ( ) ; } return hasSameSetOfFiles ; } hasRoots ( ) { return ! ! this . rootFileNames ?. length ; } markAsDirty ( ) { this . rootFileNames = undefined ; super . markAsDirty ( ) ; } getScriptFileNames ( ) { return this . rootFileNames || ts . emptyArray ; } getLanguageService ( ) { throw new Error ( "AutoImportProviderProject language service should never be used. To get the program, use `project.getCurrentProgram()`." ) ; } onAutoImportProviderSettingsChanged ( ) { throw new Error ( "AutoImportProviderProject is an auto import provider; use `markAsDirty()` instead." ) ; } onPackageJsonChange ( ) { throw new Error ( "package.json changes should be notified on an AutoImportProvider's host project" ) ; } getModuleResolutionHostForAutoImportProvider ( ) { throw new Error ( "AutoImportProviderProject cannot provide its own host; use `hostProject.getModuleResolutionHostForAutomImportProvider()` instead." ) ; } getProjectReferences ( ) { return this . hostProject . getProjectReferences ( ) ; } includePackageJsonAutoImports ( ) { return PackageJsonAutoImportPreference . Off ; } getTypeAcquisition ( ) { return { enable : false } ; } getSymlinkCache ( ) { return this . hostProject . getSymlinkCache ( ) ; } } /**
     * If a file is opened, the server will look for a tsconfig (or jsconfig)
     * and if successful create a ConfiguredProject for it.
     * Otherwise it will create an InferredProject.
     */ export class ConfiguredProject extends Project { pendingReload : ConfigFileProgramReloadLevel | undefined ; pendingReloadReason : string | undefined ; openFileWatchTriggered = new Map < string , ConfigFileProgramReloadLevel > ( ) ; canConfigFileJsonReportNoInputFiles = false ; /** Ref count to the project when opened from external project */ private externalProjectRefCount = 0 ; private projectReferences : readonly ProjectReference [ ] | undefined ; /** Potential project references before the project is actually loaded (read config file) */ potentialProjectReferences : Set < string > | undefined ; projectOptions ? : ProjectOptions | true ; isInitialLoadPending : ( ) => boolean = returnTrue ; sendLoadingProjectFinish = false ; private compilerHost ? : CompilerHost ; constructor ( configFileName , readonly canonicalConfigFilePath , projectService , documentRegistry , cachedDirectoryStructureHost ) { super ( configFileName , ProjectKind . Configured , projectService , documentRegistry , false , undefined , { } , false , undefined , cachedDirectoryStructureHost , getDirectoryPath ( configFileName ) ) ; } setCompilerHost ( host ) { this . compilerHost = host ; } getCompilerHost ( ) { return this . compilerHost ; } useSourceOfProjectReferenceRedirect ( ) { return this . languageServiceEnabled ; } getParsedCommandLine ( fileName ) { const configFileName = asNormalizedPath ( normalizePath ( fileName ) ) ; const canonicalConfigFilePath = asNormalizedPath ( this . projectService . toCanonicalFileName ( configFileName ) ) ; let configFileExistenceInfo = this . projectService . configFileExistenceInfoCache . get ( canonicalConfigFilePath ) ; if ( ! configFileExistenceInfo ) { this . projectService . configFileExistenceInfoCache . set ( canonicalConfigFilePath , configFileExistenceInfo = { exists : this . projectService . host . fileExists ( configFileName ) } ) ; } this . projectService . ensureParsedConfigUptoDate ( configFileName , canonicalConfigFilePath , configFileExistenceInfo , this ) ; if ( this . languageServiceEnabled && this . projectService . serverMode === LanguageServiceMode . Semantic ) { this . projectService . watchWildcards ( configFileName , configFileExistenceInfo , this ) ; } return configFileExistenceInfo . exists ? configFileExistenceInfo . config ! . parsedCommandLine : undefined ; } onReleaseParsedCommandLine ( fileName ) { this . releaseParsedConfig ( asNormalizedPath ( this . projectService . toCanonicalFileName ( asNormalizedPath ( normalizePath ( fileName ) ) ) ) ) ; } private releaseParsedConfig ( canonicalConfigFilePath ) { this . projectService . stopWatchingWildCards ( canonicalConfigFilePath , this ) ; this . projectService . releaseParsedConfig ( canonicalConfigFilePath , this ) ; } returns updateGraph ( ) { const isInitialLoad = this . isInitialLoadPending ( ) ; this . isInitialLoadPending = returnFalse ; const reloadLevel = this . pendingReload ; this . pendingReload = ConfigFileProgramReloadLevel . None ; let result ; switch ( reloadLevel ) { case ConfigFileProgramReloadLevel . Partial : this . openFileWatchTriggered . clear ( ) ; result = this . projectService . reloadFileNamesOfConfiguredProject ( this ) ; break ; case ConfigFileProgramReloadLevel . Full : this . openFileWatchTriggered . clear ( ) ; const reason = Debug . checkDefined ( this . pendingReloadReason ) ; this . pendingReloadReason = undefined ; this . projectService . reloadConfiguredProject ( this , reason , isInitialLoad , false ) ; result = true ; break ; default : result = super . updateGraph ( ) ; } this . compilerHost = undefined ; this . projectService . sendProjectLoadingFinishEvent ( this ) ; this . projectService . sendProjectTelemetry ( this ) ; return result ; } getCachedDirectoryStructureHost ( ) { return this . directoryStructureHost as CachedDirectoryStructureHost ; } getConfigFilePath ( ) { return asNormalizedPath ( this . getProjectName ( ) ) ; } getProjectReferences ( ) { return this . projectReferences ; } updateReferences ( refs ) { this . projectReferences = refs ; this . potentialProjectReferences = undefined ; } setPotentialProjectReference ( canonicalConfigPath ) { Debug . assert ( this . isInitialLoadPending ( ) ) ; ( this . potentialProjectReferences || ( this . potentialProjectReferences = new Set ( ) ) ) . add ( canonicalConfigPath ) ; } getResolvedProjectReferenceToRedirect ( fileName ) { const program = this . getCurrentProgram ( ) ; return program && program . getResolvedProjectReferenceToRedirect ( fileName ) ; } forEachResolvedProjectReference < T > ( cb ) { return this . getCurrentProgram ( ) ?. forEachResolvedProjectReference ( cb ) ; } enablePluginsWithOptions ( options , pluginConfigOverrides ) { const host = this . projectService . host ; if ( ! host . require ) { this . projectService . logger . info ( "Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded" ) ; return ; } const searchPaths = [ combinePaths ( this . projectService . getExecutingFilePath ( ) , "../../.." ) , ... this . projectService . pluginProbeLocations ] ; if ( this . projectService . allowLocalPluginLoads ) { const local = getDirectoryPath ( this . canonicalConfigFilePath ) ; this . projectService . logger . info ( `Local plugin loading enabled; adding ${ local } to search paths` ) ; searchPaths . unshift ( local ) ; } if ( options . plugins ) { for ( const pluginConfigEntry of options . plugins ) { this . enablePlugin ( pluginConfigEntry , searchPaths , pluginConfigOverrides ) ; } } this . enableGlobalPlugins ( options , pluginConfigOverrides ) ; } /**
         * Get the errors that dont have any file name associated
         */ getGlobalProjectErrors ( ) { return filter ( this . projectErrors , diagnostic => ! diagnostic . file ) || emptyArray ; } /**
         * Get all the project errors
         */ getAllProjectErrors ( ) { return this . projectErrors || emptyArray ; } setProjectErrors ( projectErrors ) { this . projectErrors = projectErrors ; } close ( ) { this . projectService . configFileExistenceInfoCache . forEach ( ( _configFileExistenceInfo , canonicalConfigFilePath ) => this . releaseParsedConfig ( canonicalConfigFilePath ) ) ; this . projectErrors = undefined ; this . openFileWatchTriggered . clear ( ) ; this . compilerHost = undefined ; super . close ( ) ; } addExternalProjectReference ( ) { this . externalProjectRefCount ++ ; } deleteExternalProjectReference ( ) { this . externalProjectRefCount -- ; } isSolution ( ) { return this . getRootFilesMap ( ) . size === 0 && ! this . canConfigFileJsonReportNoInputFiles ; } /** Find the configured project from the project references in project which contains the info directly */ getDefaultChildProjectFromProjectWithReferences ( info ) { return forEachResolvedProjectReferenceProject ( this , info . path , child => projectContainsInfoDirectly ( child , info ) ? child : undefined , ProjectReferenceProjectLoadKind . Find ) ; } /** Returns true if the project is needed by any of the open script info/external project */ hasOpenRef ( ) { if ( ! ! this . externalProjectRefCount ) { return true ; } if ( this . isClosed ( ) ) { return false ; } const configFileExistenceInfo = this . projectService . configFileExistenceInfoCache . get ( this . canonicalConfigFilePath ) ! ; if ( this . projectService . hasPendingProjectUpdate ( this ) ) { return ! ! configFileExistenceInfo . openFilesImpactedByConfigFile ?. size ; } return ! ! configFileExistenceInfo . openFilesImpactedByConfigFile && forEachEntry ( configFileExistenceInfo . openFilesImpactedByConfigFile , ( _value , infoPath ) => { const info = this . projectService . getScriptInfoForPath ( infoPath ) ! ; return this . containsScriptInfo ( info ) || ! ! forEachResolvedProjectReferenceProject ( this , info . path , child => child . containsScriptInfo ( info ) , ProjectReferenceProjectLoadKind . Find ) ; } ) || false ; } hasExternalProjectRef ( ) { return ! ! this . externalProjectRefCount ; } getEffectiveTypeRoots ( ) { return getEffectiveTypeRoots ( this . getCompilationSettings ( ) , this . directoryStructureHost ) || [ ] ; } updateErrorOnNoInputFiles ( fileNames ) { updateErrorForNoInputFiles ( fileNames , this . getConfigFilePath ( ) , this . getCompilerOptions ( ) . configFile ! . configFileSpecs ! , this . projectErrors ! , this . canConfigFileJsonReportNoInputFiles ) ; } } /**
     * Project whose configuration is handled externally, such as in a '.csproj'.
     * These are created only if a host explicitly calls `openExternalProject`.
     */ export class ExternalProject extends Project { excludedFiles : readonly NormalizedPath [ ] = [ ] ; constructor ( public externalProjectName , projectService , documentRegistry , compilerOptions , lastFileExceededProgramSize , public compileOnSaveEnabled , projectFilePath ? , pluginConfigOverrides ? , watchOptions ? ) { super ( externalProjectName , ProjectKind . External , projectService , documentRegistry , true , lastFileExceededProgramSize , compilerOptions , compileOnSaveEnabled , watchOptions , projectService . host , getDirectoryPath ( projectFilePath || normalizeSlashes ( externalProjectName ) ) ) ; this . enableGlobalPlugins ( this . getCompilerOptions ( ) , pluginConfigOverrides ) ; } updateGraph ( ) { const result = super . updateGraph ( ) ; this . projectService . sendProjectTelemetry ( this ) ; return result ; } getExcludedFiles ( ) { return this . excludedFiles ; } } export function isInferredProject ( project ) { return project . projectKind === ProjectKind . Inferred ; } export function isConfiguredProject ( project ) { return project . projectKind === ProjectKind . Configured ; } export function isExternalProject ( project ) { return project . projectKind === ProjectKind . External ; } }