@@ -3,20 +3,37 @@ import { commands, ExtensionContext, window, workspace } from 'vscode';
33import { OxcCommands } from './commands' ;
44import { ConfigService } from './ConfigService' ;
55import StatusBarItemHandler from './StatusBarItemHandler' ;
6+ import Formatter from './tools/formatter' ;
67import Linter from './tools/linter' ;
8+ import ToolInterface from './tools/ToolInterface' ;
79
810const outputChannelName = 'Oxc' ;
9- const linter = new Linter ( ) ;
11+ const tools : ToolInterface [ ] = [ ] ;
12+
13+ if ( process . env . SKIP_LINTER_TEST !== 'true' ) {
14+ tools . push ( new Linter ( ) ) ;
15+ }
16+ if ( process . env . SKIP_FORMATTER_TEST !== 'true' ) {
17+ tools . push ( new Formatter ( ) ) ;
18+ }
1019
1120export async function activate ( context : ExtensionContext ) {
1221 const configService = new ConfigService ( ) ;
1322
14- const outputChannel = window . createOutputChannel ( outputChannelName , {
23+ const outputChannelLint = window . createOutputChannel ( outputChannelName + ' (Lint)' , {
24+ log : true ,
25+ } ) ;
26+
27+ const outputChannelFormat = window . createOutputChannel ( outputChannelName + ' (Fmt)' , {
1528 log : true ,
1629 } ) ;
1730
18- const showOutputCommand = commands . registerCommand ( OxcCommands . ShowOutputChannel , ( ) => {
19- outputChannel . show ( ) ;
31+ const showOutputLintCommand = commands . registerCommand ( OxcCommands . ShowOutputChannelLint , ( ) => {
32+ outputChannelLint . show ( ) ;
33+ } ) ;
34+
35+ const showOutputFmtCommand = commands . registerCommand ( OxcCommands . ShowOutputChannelFmt , ( ) => {
36+ outputChannelFormat . show ( ) ;
2037 } ) ;
2138
2239 const onDidChangeWorkspaceFoldersDispose = workspace . onDidChangeWorkspaceFolders ( async ( event ) => {
@@ -31,32 +48,71 @@ export async function activate(context: ExtensionContext) {
3148 const statusBarItemHandler = new StatusBarItemHandler ( context . extension . packageJSON ?. version ) ;
3249
3350 context . subscriptions . push (
34- showOutputCommand ,
51+ showOutputLintCommand ,
52+ showOutputFmtCommand ,
3553 configService ,
36- outputChannel ,
54+ outputChannelLint ,
55+ outputChannelFormat ,
3756 onDidChangeWorkspaceFoldersDispose ,
3857 statusBarItemHandler ,
3958 ) ;
4059
4160 configService . onConfigChange = async function onConfigChange ( event ) {
42- await linter . onConfigChange ( event , configService , statusBarItemHandler ) ;
61+ await Promise . all ( tools . map ( ( tool ) => tool . onConfigChange ( event , configService , statusBarItemHandler ) ) ) ;
4362 } ;
44- const binaryPath = await linter . getBinary ( context , outputChannel , configService ) ;
45-
46- // For the linter this should never happen, but just in case.
47- if ( ! binaryPath ) {
48- statusBarItemHandler . setColorAndIcon ( 'statusBarItem.errorBackground' , 'error' ) ;
49- statusBarItemHandler . updateToolTooltip ( 'linter' , 'Error: No valid oxc language server binary found.' ) ;
50- statusBarItemHandler . show ( ) ;
51- outputChannel . error ( 'No valid oxc language server binary found.' ) ;
52- return ;
53- }
54-
55- await linter . activate ( context , binaryPath , outputChannel , configService , statusBarItemHandler ) ;
56- // Show status bar item after activation
63+
64+ const foundBinaries : string [ ] = [ ] ;
65+
66+ await Promise . all (
67+ tools . map ( async ( tool ) => {
68+ const outputChannel = tool instanceof Linter ? outputChannelLint : outputChannelFormat ;
69+ const binaryPath = await tool . getBinary ( context , outputChannel , configService ) ;
70+
71+ // For the linter this should never happen, but just in case.
72+ if ( ! binaryPath && tool instanceof Linter ) {
73+ statusBarItemHandler . setColorAndIcon ( 'statusBarItem.errorBackground' , 'error' ) ;
74+ statusBarItemHandler . updateToolTooltip ( 'linter' , 'Error: No valid oxc language server binary found.' ) ;
75+ }
76+
77+ if ( ! binaryPath && tool instanceof Formatter ) {
78+ if ( foundBinaries . some ( ( path ) => path . includes ( 'oxc_language_server' ) ) ) {
79+ // The formatter is already handled by the linter tool in this case.
80+ statusBarItemHandler . updateToolTooltip ( 'formatter' , 'oxc_language_server is used for formatting.' ) ;
81+ outputChannelFormat . appendLine ( 'oxc_language_server is used for formatting.' ) ;
82+ } else {
83+ // For the formatter we can just skip activation.
84+ statusBarItemHandler . updateToolTooltip (
85+ 'formatter' ,
86+ 'No valid oxfmt binary found. Formatter will not be activated.' ,
87+ ) ;
88+ outputChannelFormat . appendLine ( 'No valid oxfmt binary found. Formatter will not be activated.' ) ;
89+ }
90+
91+ return ;
92+ }
93+
94+ // binaryPath is guaranteed to be defined here.
95+ const binaryPathResolved = binaryPath ! ;
96+
97+ // do not activate the same binary multiple times.
98+ // This only happens when the `oxc_language_server` is used, which support both linting and formatting.
99+ //
100+ // The `linter` tool is prioritized here, so the formatter will not be activated if the linter already uses the same binary.
101+ // Because the linter source code also handles formatting in that case. (for now)
102+ if ( foundBinaries . includes ( binaryPathResolved ) ) {
103+ return ;
104+ }
105+
106+ foundBinaries . push ( binaryPathResolved ) ;
107+
108+ return tool . activate ( context , binaryPathResolved , outputChannel , configService , statusBarItemHandler ) ;
109+ } ) ,
110+ ) ;
111+
112+ // Finally show the status bar item.
57113 statusBarItemHandler . show ( ) ;
58114}
59115
60116export async function deactivate ( ) : Promise < void > {
61- await linter . deactivate ( ) ;
117+ await Promise . all ( tools . map ( ( tool ) => tool . deactivate ( ) ) ) ;
62118}
0 commit comments