import { CancellationToken } from 'vscode-languageserver' ; import { TextDocumentContentChangeEvent } from 'vscode-languageserver-textdocument' ; import { BackgroundAnalysisBase } from '../backgroundAnalysisBase' ; import { ConfigOptions , ExecutionEnvironment } from '../common/configOptions' ; import { ConsoleInterface } from '../common/console' ; import { Diagnostic } from '../common/diagnostic' ; import { FileDiagnostics } from '../common/diagnosticSink' ; import { LanguageServiceExtension } from '../common/extensibility' ; import { Range } from '../common/textRange' ; import { IndexResults } from '../languageService/documentSymbolProvider' ; import { AnalysisCompleteCallback , analyzeProgram } from './analysis' ; import { ImportResolver } from './importResolver' ; import { Indices , MaxAnalysisTime , Program } from './program' ; export class BackgroundAnalysisProgram { private _program : Program ; private _onAnalysisCompletion : AnalysisCompleteCallback | undefined ; private _indices : Indices | undefined ; constructor ( private _console , private _configOptions , private _importResolver , extension ? , private _backgroundAnalysis ? , private _maxAnalysisTime ? , private _disableChecker ? ) { this . _program = new Program ( this . _importResolver , this . _configOptions , this . _console , extension , undefined , this . _disableChecker ) ; } get configOptions ( ) { return this . _configOptions ; } get importResolver ( ) { return this . _importResolver ; } get program ( ) { return this . _program ; } get host ( ) { return this . _importResolver . host ; } get backgroundAnalysis ( ) { return this . _backgroundAnalysis ; } setConfigOptions ( configOptions ) { this . _configOptions = configOptions ; this . _backgroundAnalysis ?. setConfigOptions ( configOptions ) ; this . _program . setConfigOptions ( configOptions ) ; } setImportResolver ( importResolver ) { this . _importResolver = importResolver ; this . _backgroundAnalysis ?. setImportResolver ( importResolver ) ; this . _program . setImportResolver ( importResolver ) ; this . _configOptions . getExecutionEnvironments ( ) . forEach ( ( e ) => this . _ensurePartialStubPackages ( e ) ) ; } setTrackedFiles ( filePaths ) { this . _backgroundAnalysis ?. setTrackedFiles ( filePaths ) ; const diagnostics = this . _program . setTrackedFiles ( filePaths ) ; this . _reportDiagnosticsForRemovedFiles ( diagnostics ) ; } setAllowedThirdPartyImports ( importNames ) { this . _backgroundAnalysis ?. setAllowedThirdPartyImports ( importNames ) ; this . _program . setAllowedThirdPartyImports ( importNames ) ; } setFileOpened ( filePath , version , contents , isTracked ) { this . _backgroundAnalysis ?. setFileOpened ( filePath , version , [ { text : contents } ] , isTracked ) ; this . _program . setFileOpened ( filePath , version , [ { text : contents } ] , isTracked ) ; } updateOpenFileContents ( path , version , contents , isTracked ) { this . _backgroundAnalysis ?. setFileOpened ( path , version , contents , isTracked ) ; this . _program . setFileOpened ( path , version , contents , isTracked ) ; this . markFilesDirty ( [ path ] , true ) ; } setFileClosed ( filePath ) { this . _backgroundAnalysis ?. setFileClosed ( filePath ) ; const diagnostics = this . _program . setFileClosed ( filePath ) ; this . _reportDiagnosticsForRemovedFiles ( diagnostics ) ; } markAllFilesDirty ( evenIfContentsAreSame ) { this . _backgroundAnalysis ?. markAllFilesDirty ( evenIfContentsAreSame ) ; this . _program . markAllFilesDirty ( evenIfContentsAreSame ) ; } markFilesDirty ( filePaths , evenIfContentsAreSame ) { this . _backgroundAnalysis ?. markFilesDirty ( filePaths , evenIfContentsAreSame ) ; this . _program . markFilesDirty ( filePaths , evenIfContentsAreSame ) ; } setCompletionCallback ( callback ? ) { this . _onAnalysisCompletion = callback ; this . _backgroundAnalysis ?. setCompletionCallback ( callback ) ; } startAnalysis ( token ) { if ( this . _backgroundAnalysis ) { this . _backgroundAnalysis . startAnalysis ( this . _indices , token ) ; return false ; } return analyzeProgram ( this . _program , this . _maxAnalysisTime , this . _configOptions , this . _onAnalysisCompletion , this . _console , token ) ; } test_setIndexing ( workspaceIndices , libraryIndices ) { const indices = this . _getIndices ( ) ; for ( const [ filePath , indexResults ] of workspaceIndices ) { indices . setWorkspaceIndex ( filePath , indexResults ) ; } for ( const [ execEnvRoot , map ] of libraryIndices ) { for ( const [ libraryPath , indexResults ] of map ) { indices . setIndex ( execEnvRoot , libraryPath , indexResults ) ; } } } startIndexing ( ) { if ( ! this . _configOptions . indexing ) { return ; } this . _backgroundAnalysis ?. startIndexing ( this . _configOptions , this . host . kind , this . _getIndices ( ) ) ; } refreshIndexing ( ) { if ( ! this . _configOptions . indexing ) { return ; } this . _backgroundAnalysis ?. refreshIndexing ( this . _configOptions , this . host . kind , this . _indices ) ; } cancelIndexing ( ) { this . _backgroundAnalysis ?. cancelIndexing ( this . _configOptions ) ; } getIndexing ( filePath ) { return this . _indices ?. getIndex ( this . _configOptions . findExecEnvironment ( filePath ) . root ) ; } async getDiagnosticsForRange ( filePath , range , token ) { if ( this . _backgroundAnalysis ) { return this . _backgroundAnalysis . getDiagnosticsForRange ( filePath , range , token ) ; } return this . _program . getDiagnosticsForRange ( filePath , range ) ; } async writeTypeStub ( targetImportPath , targetIsSingleFile , stubPath , token ) { if ( this . _backgroundAnalysis ) { return this . _backgroundAnalysis . writeTypeStub ( targetImportPath , targetIsSingleFile , stubPath , token ) ; } analyzeProgram ( this . _program , undefined , this . _configOptions , this . _onAnalysisCompletion , this . _console , token ) ; return this . _program . writeTypeStub ( targetImportPath , targetIsSingleFile , stubPath , token ) ; } invalidateAndForceReanalysis ( rebuildLibraryIndexing ) { if ( rebuildLibraryIndexing ) { this . refreshIndexing ( ) ; } this . _backgroundAnalysis ?. invalidateAndForceReanalysis ( ) ; this . _importResolver . invalidateCache ( ) ; this . _program . markAllFilesDirty ( true ) ; } restart ( ) { this . _backgroundAnalysis ?. restart ( ) ; } private _ensurePartialStubPackages ( execEnv ) { this . _backgroundAnalysis ?. ensurePartialStubPackages ( execEnv . root ) ; return this . _importResolver . ensurePartialStubPackages ( execEnv ) ; } private _getIndices ( ) { if ( ! this . _indices ) { const program = this . _program ; const map = new Map < string | undefined , Map < string , IndexResults > > ( ) ; this . _indices = { setWorkspaceIndex ( path , indexResults ) { program . getSourceFile ( path ) ?. cacheIndexResults ( indexResults ) ; } , getIndex ( execEnv ) { return map . get ( execEnv ) ; } , setIndex ( execEnv , path , indexResults ) { let indicesMap = map . get ( execEnv ) ; if ( ! indicesMap ) { indicesMap = new Map < string , IndexResults > ( ) ; map . set ( execEnv , indicesMap ) ; } indicesMap . set ( path , indexResults ) ; } , reset ( ) { map . clear ( ) ; } , } ; } return this . _indices ! ; } private _reportDiagnosticsForRemovedFiles ( fileDiags ) { if ( fileDiags . length > 0 ) { if ( ! this . _backgroundAnalysis && this . _onAnalysisCompletion ) { this . _onAnalysisCompletion ( { diagnostics : fileDiags , filesInProgram : this . _program . getFileCount ( ) , filesRequiringAnalysis : this . _program . getFilesToAnalyzeCount ( ) , checkingOnlyOpenFiles : this . _program . isCheckingOnlyOpenFiles ( ) , fatalErrorOccurred : false , configParseErrorOccurred : false , elapsedTime : 0 , } ) ; } } } } export type BackgroundAnalysisProgramFactory = ( console : ConsoleInterface , configOptions : ConfigOptions , importResolver : ImportResolver , extension ? : LanguageServiceExtension , backgroundAnalysis ? : BackgroundAnalysisBase , maxAnalysisTime ? : MaxAnalysisTime ) => BackgroundAnalysisProgram ;