@@ -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,60 @@ 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 ;
1597+ const log = ( message : string ) => this . projectService . logger . info ( message ) ;
15891598 const logError = ( message : string ) => {
1590- ( errorLogs || ( errorLogs = [ ] ) ) . push ( message ) ;
1599+ ( errorLogs ?? = [ ] ) . push ( message ) ;
15911600 } ;
1601+ const resolvedModule = firstDefined ( searchPaths , searchPath =>
1602+ Project . resolveModule ( pluginConfigEntry . name , searchPath , this . projectService . host , log , logError ) as PluginModuleFactory | undefined ) ;
1603+ return { pluginConfigEntry, pluginConfigOverrides, resolvedModule, errorLogs } ;
1604+ }
15921605
1593- let resolvedModule : any | undefined ;
1594- if ( this . projectService . host . importServicePlugin ) {
1595- for ( const searchPath of searchPaths ) {
1606+ /**
1607+ * Performs the initial steps of enabling a plugin by finding and instantiating the module for a plugin asynchronously using dynamic `import`.
1608+ */
1609+ /*@internal */
1610+ async beginEnablePluginAsync ( pluginConfigEntry : PluginImport , searchPaths : string [ ] , pluginConfigOverrides : Map < any > | undefined ) : Promise < BeginEnablePluginResult > {
1611+ Debug . assertIsDefined ( this . projectService . host . importServicePlugin ) ;
1612+
1613+ let errorLogs : string [ ] | undefined ;
1614+ let resolvedModule : PluginModuleFactory | undefined ;
1615+ for ( const searchPath of searchPaths ) {
1616+ try {
15961617 const result = await this . projectService . host . importServicePlugin ( searchPath , pluginConfigEntry . name ) ;
15971618 if ( result . error ) {
1598- logError ( result . error . toString ( ) ) ;
1619+ ( errorLogs ??= [ ] ) . push ( result . error . toString ( ) ) ;
15991620 }
16001621 else {
1601- resolvedModule = result . module ;
1622+ resolvedModule = result . module as PluginModuleFactory ;
16021623 break ;
16031624 }
1604-
1625+ }
1626+ catch ( e ) {
1627+ ( errorLogs ??= [ ] ) . push ( `${ e } ` ) ;
16051628 }
16061629 }
1607- else {
1608- resolvedModule = firstDefined ( searchPaths , searchPath =>
1609- Project . resolveModule ( pluginConfigEntry . name , searchPath , this . projectService . host , log , logError ) as PluginModuleFactory | undefined ) ;
1610- }
1630+ return { pluginConfigEntry, pluginConfigOverrides, resolvedModule, errorLogs } ;
1631+ }
16111632
1633+ /**
1634+ * Performs the remaining steps of enabling a plugin after its module has been instantiated.
1635+ */
1636+ /*@internal */
1637+ endEnablePlugin ( { pluginConfigEntry, pluginConfigOverrides, resolvedModule, errorLogs } : BeginEnablePluginResult ) {
16121638 if ( resolvedModule ) {
16131639 const configurationOverride = pluginConfigOverrides && pluginConfigOverrides . get ( pluginConfigEntry . name ) ;
16141640 if ( configurationOverride ) {
@@ -1621,11 +1647,15 @@ namespace ts.server {
16211647 this . enableProxy ( resolvedModule , pluginConfigEntry ) ;
16221648 }
16231649 else {
1624- forEach ( errorLogs , log ) ;
1650+ forEach ( errorLogs , message => this . projectService . logger . info ( message ) ) ;
16251651 this . projectService . logger . info ( `Couldn't find ${ pluginConfigEntry . name } ` ) ;
16261652 }
16271653 }
16281654
1655+ protected enablePlugin ( pluginConfigEntry : PluginImport , searchPaths : string [ ] , pluginConfigOverrides : Map < any > | undefined ) : void {
1656+ this . projectService . requestEnablePlugin ( this , pluginConfigEntry , searchPaths , pluginConfigOverrides ) ;
1657+ }
1658+
16291659 private enableProxy ( pluginModuleFactory : PluginModuleFactory , configEntry : PluginImport ) {
16301660 try {
16311661 if ( typeof pluginModuleFactory !== "function" ) {
@@ -2289,10 +2319,10 @@ namespace ts.server {
22892319 }
22902320
22912321 /*@internal */
2292- async enablePluginsWithOptions ( options : CompilerOptions , pluginConfigOverrides : ESMap < string , any > | undefined ) : Promise < void > {
2322+ enablePluginsWithOptions ( options : CompilerOptions , pluginConfigOverrides : ESMap < string , any > | undefined ) : void {
22932323 const host = this . projectService . host ;
22942324
2295- if ( ! host . require ) {
2325+ if ( ! host . require && ! host . importServicePlugin ) {
22962326 this . projectService . logger . info ( "Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded" ) ;
22972327 return ;
22982328 }
@@ -2310,7 +2340,7 @@ namespace ts.server {
23102340 // Enable tsconfig-specified plugins
23112341 if ( options . plugins ) {
23122342 for ( const pluginConfigEntry of options . plugins ) {
2313- await this . enablePlugin ( pluginConfigEntry , searchPaths , pluginConfigOverrides ) ;
2343+ this . enablePlugin ( pluginConfigEntry , searchPaths , pluginConfigOverrides ) ;
23142344 }
23152345 }
23162346
0 commit comments