@@ -101,6 +101,14 @@ namespace ts.server {
101101
102102 export type PluginModuleFactory = ( mod : { typescript : typeof ts } ) => PluginModule ;
103103
104+ /* @internal */
105+ export interface BeginEnablePluginResult {
106+ pluginConfigEntry : PluginImport ;
107+ pluginConfigOverrides : Map < any > | undefined ;
108+ resolvedModule : PluginModuleFactory | undefined ;
109+ errorLogs : string [ ] | undefined ;
110+ }
111+
104112 /**
105113 * The project root can be script info - if root is present,
106114 * or it could be just normalized path if root wasn't present on the host(only for non inferred project)
@@ -133,6 +141,7 @@ namespace ts.server {
133141 private externalFiles : SortedReadonlyArray < string > | undefined ;
134142 private missingFilesMap : ESMap < Path , FileWatcher > | undefined ;
135143 private generatedFilesMap : GeneratedFileWatcherMap | undefined ;
144+
136145 private plugins : PluginModuleWithName [ ] = [ ] ;
137146
138147 /*@internal */
@@ -1545,10 +1554,10 @@ namespace ts.server {
15451554 return ! ! this . program && this . program . isSourceOfProjectReferenceRedirect ( fileName ) ;
15461555 }
15471556
1548- protected async enableGlobalPlugins ( options : CompilerOptions , pluginConfigOverrides : Map < any > | undefined ) : Promise < void > {
1557+ protected enableGlobalPlugins ( options : CompilerOptions , pluginConfigOverrides : Map < any > | undefined ) : void {
15491558 const host = this . projectService . host ;
15501559
1551- if ( ! host . require ) {
1560+ if ( ! host . require && ! host . importServicePlugin ) {
15521561 this . projectService . logger . info ( "Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded" ) ;
15531562 return ;
15541563 }
@@ -1572,43 +1581,58 @@ namespace ts.server {
15721581 // Provide global: true so plugins can detect why they can't find their config
15731582 this . projectService . logger . info ( `Loading global plugin ${ globalPluginName } ` ) ;
15741583
1575- await this . enablePlugin ( { name : globalPluginName , global : true } as PluginImport , searchPaths , pluginConfigOverrides ) ;
1584+ this . enablePlugin ( { name : globalPluginName , global : true } as PluginImport , searchPaths , pluginConfigOverrides ) ;
15761585 }
15771586 }
15781587 }
15791588
1580- protected async enablePlugin ( pluginConfigEntry : PluginImport , searchPaths : string [ ] , pluginConfigOverrides : Map < any > | undefined ) : Promise < void > {
1581- this . projectService . logger . info ( `Enabling plugin ${ pluginConfigEntry . name } from candidate paths: ${ searchPaths . join ( "," ) } ` ) ;
1582- if ( ! pluginConfigEntry . name || parsePackageName ( pluginConfigEntry . name ) . rest ) {
1583- this . projectService . logger . info ( `Skipped loading plugin ${ pluginConfigEntry . name || JSON . stringify ( pluginConfigEntry ) } because only package name is allowed plugin name` ) ;
1584- return ;
1585- }
1589+ /**
1590+ * Performs the initial steps of enabling a plugin by finding and instantiating the module for a plugin synchronously using 'require'.
1591+ */
1592+ /* @internal */
1593+ beginEnablePluginSync ( pluginConfigEntry : PluginImport , searchPaths : string [ ] , pluginConfigOverrides : Map < any > | undefined ) : BeginEnablePluginResult {
1594+ Debug . assertIsDefined ( this . projectService . host . require ) ;
15861595
1587- const log = ( message : string ) => this . projectService . logger . info ( message ) ;
15881596 let errorLogs : string [ ] | undefined ;
1589- const logError = ( message : string ) => {
1590- ( errorLogs || ( errorLogs = [ ] ) ) . push ( message ) ;
1591- } ;
1597+ const log = ( message : string ) => this . projectService . logger . info ( message ) ;
1598+ const logError = ( message : string ) => { ( errorLogs ??= [ ] ) . push ( message ) ; } ;
1599+ const resolvedModule = firstDefined ( searchPaths , searchPath =>
1600+ Project . resolveModule ( pluginConfigEntry . name , searchPath , this . projectService . host , log , logError ) as PluginModuleFactory | undefined ) ;
1601+ return { pluginConfigEntry, pluginConfigOverrides, resolvedModule, errorLogs } ;
1602+ }
1603+
1604+ /**
1605+ * Performs the initial steps of enabling a plugin by finding and instantiating the module for a plugin asynchronously using dynamic `import`.
1606+ */
1607+ /*@internal */
1608+ async beginEnablePluginAsync ( pluginConfigEntry : PluginImport , searchPaths : string [ ] , pluginConfigOverrides : Map < any > | undefined ) : Promise < BeginEnablePluginResult > {
1609+ Debug . assertIsDefined ( this . projectService . host . importServicePlugin ) ;
15921610
1593- let resolvedModule : any | undefined ;
1594- if ( this . projectService . host . importServicePlugin ) {
1595- for ( const searchPath of searchPaths ) {
1611+ let errorLogs : string [ ] | undefined ;
1612+ let resolvedModule : PluginModuleFactory | undefined ;
1613+ for ( const searchPath of searchPaths ) {
1614+ try {
15961615 const result = await this . projectService . host . importServicePlugin ( searchPath , pluginConfigEntry . name ) ;
15971616 if ( result . error ) {
1598- logError ( result . error . toString ( ) ) ;
1617+ ( errorLogs ??= [ ] ) . push ( result . error . toString ( ) ) ;
15991618 }
16001619 else {
1601- resolvedModule = result . module ;
1620+ resolvedModule = result . module as PluginModuleFactory ;
16021621 break ;
16031622 }
1604-
1623+ }
1624+ catch ( e ) {
1625+ ( errorLogs ??= [ ] ) . push ( `${ e } ` ) ;
16051626 }
16061627 }
1607- else {
1608- resolvedModule = firstDefined ( searchPaths , searchPath =>
1609- Project . resolveModule ( pluginConfigEntry . name , searchPath , this . projectService . host , log , logError ) as PluginModuleFactory | undefined ) ;
1610- }
1628+ return { pluginConfigEntry, pluginConfigOverrides, resolvedModule, errorLogs } ;
1629+ }
16111630
1631+ /**
1632+ * Performs the remaining steps of enabling a plugin after its module has been instantiated.
1633+ */
1634+ /*@internal */
1635+ endEnablePlugin ( { pluginConfigEntry, pluginConfigOverrides, resolvedModule, errorLogs } : BeginEnablePluginResult ) {
16121636 if ( resolvedModule ) {
16131637 const configurationOverride = pluginConfigOverrides && pluginConfigOverrides . get ( pluginConfigEntry . name ) ;
16141638 if ( configurationOverride ) {
@@ -1621,11 +1645,15 @@ namespace ts.server {
16211645 this . enableProxy ( resolvedModule , pluginConfigEntry ) ;
16221646 }
16231647 else {
1624- forEach ( errorLogs , log ) ;
1648+ forEach ( errorLogs , message => this . projectService . logger . info ( message ) ) ;
16251649 this . projectService . logger . info ( `Couldn't find ${ pluginConfigEntry . name } ` ) ;
16261650 }
16271651 }
16281652
1653+ protected enablePlugin ( pluginConfigEntry : PluginImport , searchPaths : string [ ] , pluginConfigOverrides : Map < any > | undefined ) : void {
1654+ this . projectService . requestEnablePlugin ( this , pluginConfigEntry , searchPaths , pluginConfigOverrides ) ;
1655+ }
1656+
16291657 private enableProxy ( pluginModuleFactory : PluginModuleFactory , configEntry : PluginImport ) {
16301658 try {
16311659 if ( typeof pluginModuleFactory !== "function" ) {
@@ -2289,10 +2317,10 @@ namespace ts.server {
22892317 }
22902318
22912319 /*@internal */
2292- async enablePluginsWithOptions ( options : CompilerOptions , pluginConfigOverrides : ESMap < string , any > | undefined ) : Promise < void > {
2320+ enablePluginsWithOptions ( options : CompilerOptions , pluginConfigOverrides : ESMap < string , any > | undefined ) : void {
22932321 const host = this . projectService . host ;
22942322
2295- if ( ! host . require ) {
2323+ if ( ! host . require && ! host . importServicePlugin ) {
22962324 this . projectService . logger . info ( "Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded" ) ;
22972325 return ;
22982326 }
@@ -2310,7 +2338,7 @@ namespace ts.server {
23102338 // Enable tsconfig-specified plugins
23112339 if ( options . plugins ) {
23122340 for ( const pluginConfigEntry of options . plugins ) {
2313- await this . enablePlugin ( pluginConfigEntry , searchPaths , pluginConfigOverrides ) ;
2341+ this . enablePlugin ( pluginConfigEntry , searchPaths , pluginConfigOverrides ) ;
23142342 }
23152343 }
23162344
0 commit comments