@@ -101,6 +101,14 @@ namespace ts.server {
101
101
102
102
export type PluginModuleFactory = ( mod : { typescript : typeof ts } ) => PluginModule ;
103
103
104
+ /* @internal */
105
+ export interface BeginEnablePluginResult {
106
+ pluginConfigEntry : PluginImport ;
107
+ pluginConfigOverrides : Map < any > | undefined ;
108
+ resolvedModule : PluginModuleFactory | undefined ;
109
+ errorLogs : string [ ] | undefined ;
110
+ }
111
+
104
112
/**
105
113
* The project root can be script info - if root is present,
106
114
* 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 {
133
141
private externalFiles : SortedReadonlyArray < string > | undefined ;
134
142
private missingFilesMap : ESMap < Path , FileWatcher > | undefined ;
135
143
private generatedFilesMap : GeneratedFileWatcherMap | undefined ;
144
+
136
145
private plugins : PluginModuleWithName [ ] = [ ] ;
137
146
138
147
/*@internal */
@@ -1545,10 +1554,10 @@ namespace ts.server {
1545
1554
return ! ! this . program && this . program . isSourceOfProjectReferenceRedirect ( fileName ) ;
1546
1555
}
1547
1556
1548
- protected async enableGlobalPlugins ( options : CompilerOptions , pluginConfigOverrides : Map < any > | undefined ) : Promise < void > {
1557
+ protected enableGlobalPlugins ( options : CompilerOptions , pluginConfigOverrides : Map < any > | undefined ) : void {
1549
1558
const host = this . projectService . host ;
1550
1559
1551
- if ( ! host . require ) {
1560
+ if ( ! host . require && ! host . importServicePlugin ) {
1552
1561
this . projectService . logger . info ( "Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded" ) ;
1553
1562
return ;
1554
1563
}
@@ -1572,43 +1581,58 @@ namespace ts.server {
1572
1581
// Provide global: true so plugins can detect why they can't find their config
1573
1582
this . projectService . logger . info ( `Loading global plugin ${ globalPluginName } ` ) ;
1574
1583
1575
- await this . enablePlugin ( { name : globalPluginName , global : true } as PluginImport , searchPaths , pluginConfigOverrides ) ;
1584
+ this . enablePlugin ( { name : globalPluginName , global : true } as PluginImport , searchPaths , pluginConfigOverrides ) ;
1576
1585
}
1577
1586
}
1578
1587
}
1579
1588
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 ) ;
1586
1595
1587
- const log = ( message : string ) => this . projectService . logger . info ( message ) ;
1588
1596
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 ) ;
1592
1610
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 {
1596
1615
const result = await this . projectService . host . importServicePlugin ( searchPath , pluginConfigEntry . name ) ;
1597
1616
if ( result . error ) {
1598
- logError ( result . error . toString ( ) ) ;
1617
+ ( errorLogs ??= [ ] ) . push ( result . error . toString ( ) ) ;
1599
1618
}
1600
1619
else {
1601
- resolvedModule = result . module ;
1620
+ resolvedModule = result . module as PluginModuleFactory ;
1602
1621
break ;
1603
1622
}
1604
-
1623
+ }
1624
+ catch ( e ) {
1625
+ ( errorLogs ??= [ ] ) . push ( `${ e } ` ) ;
1605
1626
}
1606
1627
}
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
+ }
1611
1630
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 ) {
1612
1636
if ( resolvedModule ) {
1613
1637
const configurationOverride = pluginConfigOverrides && pluginConfigOverrides . get ( pluginConfigEntry . name ) ;
1614
1638
if ( configurationOverride ) {
@@ -1621,11 +1645,15 @@ namespace ts.server {
1621
1645
this . enableProxy ( resolvedModule , pluginConfigEntry ) ;
1622
1646
}
1623
1647
else {
1624
- forEach ( errorLogs , log ) ;
1648
+ forEach ( errorLogs , message => this . projectService . logger . info ( message ) ) ;
1625
1649
this . projectService . logger . info ( `Couldn't find ${ pluginConfigEntry . name } ` ) ;
1626
1650
}
1627
1651
}
1628
1652
1653
+ protected enablePlugin ( pluginConfigEntry : PluginImport , searchPaths : string [ ] , pluginConfigOverrides : Map < any > | undefined ) : void {
1654
+ this . projectService . requestEnablePlugin ( this , pluginConfigEntry , searchPaths , pluginConfigOverrides ) ;
1655
+ }
1656
+
1629
1657
private enableProxy ( pluginModuleFactory : PluginModuleFactory , configEntry : PluginImport ) {
1630
1658
try {
1631
1659
if ( typeof pluginModuleFactory !== "function" ) {
@@ -2289,10 +2317,10 @@ namespace ts.server {
2289
2317
}
2290
2318
2291
2319
/*@internal */
2292
- async enablePluginsWithOptions ( options : CompilerOptions , pluginConfigOverrides : ESMap < string , any > | undefined ) : Promise < void > {
2320
+ enablePluginsWithOptions ( options : CompilerOptions , pluginConfigOverrides : ESMap < string , any > | undefined ) : void {
2293
2321
const host = this . projectService . host ;
2294
2322
2295
- if ( ! host . require ) {
2323
+ if ( ! host . require && ! host . importServicePlugin ) {
2296
2324
this . projectService . logger . info ( "Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded" ) ;
2297
2325
return ;
2298
2326
}
@@ -2310,7 +2338,7 @@ namespace ts.server {
2310
2338
// Enable tsconfig-specified plugins
2311
2339
if ( options . plugins ) {
2312
2340
for ( const pluginConfigEntry of options . plugins ) {
2313
- await this . enablePlugin ( pluginConfigEntry , searchPaths , pluginConfigOverrides ) ;
2341
+ this . enablePlugin ( pluginConfigEntry , searchPaths , pluginConfigOverrides ) ;
2314
2342
}
2315
2343
}
2316
2344
0 commit comments