1
1
'use strict' ;
2
2
3
- import { StatusBarItem , window , StatusBarAlignment , TextEditor , Uri , commands , workspace , version } from "vscode" ;
3
+ import * as fse from "fs-extra" ;
4
+ import { StatusBarItem , window , StatusBarAlignment , TextEditor , Uri , commands , workspace , version , languages , Command , ExtensionContext } from "vscode" ;
4
5
import { Commands } from "./commands" ;
5
6
import { Disposable } from "vscode-languageclient" ;
6
7
import * as path from "path" ;
7
8
import { apiManager } from "./apiManager" ;
8
9
import * as semver from "semver" ;
10
+ import { ACTIVE_BUILD_TOOL_STATE } from "./settings" ;
11
+ import { BuildFileStatusItemFactory , RuntimeStatusItemFactory , StatusCommands , supportsLanguageStatus } from "./languageStatusItemFactory" ;
12
+ import { getJavaConfiguration } from "./utils" ;
13
+ import { hasBuildToolConflicts } from "./extension" ;
9
14
10
15
class RuntimeStatusBarProvider implements Disposable {
11
16
private statusBarItem : StatusBarItem ;
17
+ private runtimeStatusItem : any ;
18
+ private buildFileStatusItem : any ;
12
19
private javaProjects : Map < string , IProjectInfo > ;
13
20
private fileProjectMapping : Map < string , string > ;
14
21
private storagePath : string | undefined ;
@@ -24,17 +31,20 @@ class RuntimeStatusBarProvider implements Disposable {
24
31
this . isAdvancedStatusBarItem = semver . gte ( version , "1.57.0" ) ;
25
32
}
26
33
27
- public async initialize ( storagePath ?: string ) : Promise < void > {
34
+ public async initialize ( context : ExtensionContext ) : Promise < void > {
28
35
// ignore the hash part to make it compatible in debug mode.
36
+ const storagePath = context . storagePath ;
29
37
if ( storagePath ) {
30
38
this . storagePath = Uri . file ( path . join ( storagePath , ".." , ".." ) ) . fsPath ;
31
39
}
32
40
33
- if ( this . isAdvancedStatusBarItem ) {
34
- this . statusBarItem = ( window . createStatusBarItem as any ) ( "java.runtimeStatus" , StatusBarAlignment . Right , 0 ) ;
35
- ( this . statusBarItem as any ) . name = "Java Runtime Configuration" ;
36
- } else {
37
- this . statusBarItem = window . createStatusBarItem ( StatusBarAlignment . Right , 0 ) ;
41
+ if ( ! supportsLanguageStatus ( ) ) {
42
+ if ( this . isAdvancedStatusBarItem ) {
43
+ this . statusBarItem = ( window . createStatusBarItem as any ) ( "java.runtimeStatus" , StatusBarAlignment . Right , 0 ) ;
44
+ ( this . statusBarItem as any ) . name = "Java Runtime Configuration" ;
45
+ } else {
46
+ this . statusBarItem = window . createStatusBarItem ( StatusBarAlignment . Right , 0 ) ;
47
+ }
38
48
}
39
49
40
50
let projectUriStrings : string [ ] ;
@@ -48,38 +58,48 @@ class RuntimeStatusBarProvider implements Disposable {
48
58
this . javaProjects . set ( Uri . parse ( uri ) . fsPath , undefined ) ;
49
59
}
50
60
51
- this . statusBarItem . command = {
52
- title : "Configure Java Runtime" ,
53
- command : "workbench.action.openSettings" ,
54
- arguments : [ "java.configuration.runtimes" ] ,
55
- } ;
61
+ if ( ! supportsLanguageStatus ( ) ) {
62
+ this . statusBarItem . command = StatusCommands . configureJavaRuntimeCommand ;
63
+ }
56
64
57
65
this . disposables . push ( window . onDidChangeActiveTextEditor ( ( textEditor ) => {
58
- this . updateItem ( textEditor ) ;
66
+ this . updateItem ( context , textEditor ) ;
59
67
} ) ) ;
60
68
61
69
this . disposables . push ( apiManager . getApiInstance ( ) . onDidProjectsImport ( async ( uris : Uri [ ] ) => {
62
70
for ( const uri of uris ) {
63
71
this . javaProjects . set ( uri . fsPath , this . javaProjects . get ( uri . fsPath ) ) ;
64
72
}
65
- await this . updateItem ( window . activeTextEditor ) ;
73
+ await this . updateItem ( context , window . activeTextEditor ) ;
66
74
} ) ) ;
67
75
68
76
this . disposables . push ( apiManager . getApiInstance ( ) . onDidClasspathUpdate ( async ( e : Uri ) => {
69
77
for ( const projectPath of this . javaProjects . keys ( ) ) {
70
78
if ( path . relative ( projectPath , e . fsPath ) === '' ) {
71
79
this . javaProjects . set ( projectPath , undefined ) ;
72
- await this . updateItem ( window . activeTextEditor ) ;
80
+ await this . updateItem ( context , window . activeTextEditor ) ;
73
81
return ;
74
82
}
75
83
}
76
84
} ) ) ;
77
85
78
- await this . updateItem ( window . activeTextEditor ) ;
86
+ await this . updateItem ( context , window . activeTextEditor ) ;
87
+ }
88
+
89
+ private hideRuntimeStatusItem ( ) : void {
90
+ this . runtimeStatusItem ?. dispose ( ) ;
91
+ this . runtimeStatusItem = undefined ;
92
+ }
93
+
94
+ private hideBuildFileStatusItem ( ) : void {
95
+ this . buildFileStatusItem ?. dispose ( ) ;
96
+ this . buildFileStatusItem = undefined ;
79
97
}
80
98
81
99
public dispose ( ) : void {
82
- this . statusBarItem . dispose ( ) ;
100
+ this . statusBarItem ?. dispose ( ) ;
101
+ this . runtimeStatusItem ?. dispose ( ) ;
102
+ this . buildFileStatusItem ?. dispose ( ) ;
83
103
for ( const disposable of this . disposables ) {
84
104
disposable . dispose ( ) ;
85
105
}
@@ -140,28 +160,54 @@ class RuntimeStatusBarProvider implements Disposable {
140
160
return undefined ;
141
161
}
142
162
143
- private async updateItem ( textEditor : TextEditor ) : Promise < void > {
144
- if ( ! textEditor || path . extname ( textEditor . document . fileName ) !== ".java" ) {
145
- this . statusBarItem . hide ( ) ;
163
+ private async updateItem ( context : ExtensionContext , textEditor : TextEditor ) : Promise < void > {
164
+ if ( ! textEditor || path . extname ( textEditor . document . fileName ) !== ".java" && ! supportsLanguageStatus ( ) ) {
165
+ this . statusBarItem ? .hide ( ) ;
146
166
return ;
147
167
}
148
168
149
169
const uri : Uri = textEditor . document . uri ;
150
170
const projectPath : string = this . findOwnerProject ( uri ) ;
151
171
if ( ! projectPath ) {
152
- this . statusBarItem . hide ( ) ;
172
+ if ( supportsLanguageStatus ( ) ) {
173
+ this . hideRuntimeStatusItem ( ) ;
174
+ this . hideBuildFileStatusItem ( ) ;
175
+ } else {
176
+ this . statusBarItem ?. hide ( ) ;
177
+ }
153
178
return ;
154
179
}
155
180
156
181
const projectInfo : IProjectInfo = await this . getProjectInfo ( projectPath ) ;
157
182
if ( ! projectInfo ) {
158
- this . statusBarItem . hide ( ) ;
183
+ if ( supportsLanguageStatus ( ) ) {
184
+ this . hideRuntimeStatusItem ( ) ;
185
+ this . hideBuildFileStatusItem ( ) ;
186
+ } else {
187
+ this . statusBarItem ?. hide ( ) ;
188
+ }
159
189
return ;
160
190
}
161
191
162
- this . statusBarItem . text = this . getJavaRuntimeFromVersion ( projectInfo . sourceLevel ) ;
163
- this . statusBarItem . tooltip = projectInfo . vmInstallPath ? `Language Level: ${ this . statusBarItem . text } <${ projectInfo . vmInstallPath } >` : "Configure Java Runtime" ;
164
- this . statusBarItem . show ( ) ;
192
+ const text = this . getJavaRuntimeFromVersion ( projectInfo . sourceLevel ) ;
193
+ if ( supportsLanguageStatus ( ) ) {
194
+ const buildFilePath = await this . getBuildFilePath ( context , projectPath ) ;
195
+ if ( ! this . runtimeStatusItem ) {
196
+ this . runtimeStatusItem = RuntimeStatusItemFactory . create ( text , projectInfo . vmInstallPath ) ;
197
+ if ( buildFilePath ) {
198
+ this . buildFileStatusItem = BuildFileStatusItemFactory . create ( buildFilePath ) ;
199
+ }
200
+ } else {
201
+ RuntimeStatusItemFactory . update ( this . runtimeStatusItem , text , projectInfo . vmInstallPath ) ;
202
+ if ( buildFilePath ) {
203
+ BuildFileStatusItemFactory . update ( this . buildFileStatusItem , buildFilePath ) ;
204
+ }
205
+ }
206
+ } else {
207
+ this . statusBarItem . text = text ;
208
+ this . statusBarItem . tooltip = projectInfo . vmInstallPath ? `Language Level: ${ this . statusBarItem . text } <${ projectInfo . vmInstallPath } >` : "Configure Java Runtime" ;
209
+ this . statusBarItem . show ( ) ;
210
+ }
165
211
}
166
212
167
213
private isDefaultProjectPath ( fsPath : string ) {
@@ -181,6 +227,45 @@ class RuntimeStatusBarProvider implements Disposable {
181
227
182
228
return `JavaSE-${ ver } ` ;
183
229
}
230
+
231
+ private async getBuildFilePath ( context : ExtensionContext , projectPath : string ) : Promise < string | undefined > {
232
+ const isMavenEnabled : boolean = getJavaConfiguration ( ) . get < boolean > ( "import.maven.enabled" ) ;
233
+ const isGradleEnabled : boolean = getJavaConfiguration ( ) . get < boolean > ( "import.gradle.enabled" ) ;
234
+ if ( isMavenEnabled && isGradleEnabled ) {
235
+ let buildFilePath : string | undefined ;
236
+ const activeBuildTool : string | undefined = context . workspaceState . get ( ACTIVE_BUILD_TOOL_STATE ) ;
237
+ if ( ! activeBuildTool ) {
238
+ if ( ! hasBuildToolConflicts ( ) ) {
239
+ // only one build tool exists in the project
240
+ buildFilePath = await this . getBuildFilePathFromNames ( projectPath , [ "pom.xml" , "build.gradle" , "build.gradle.kts" , "settings.gradle" , "settings.gradle.kts" ] ) ;
241
+ } else {
242
+ // the user has not resolved build conflicts yet
243
+ return undefined ;
244
+ }
245
+ } else if ( activeBuildTool . toLocaleLowerCase ( ) . includes ( "maven" ) ) {
246
+ buildFilePath = await this . getBuildFilePathFromNames ( projectPath , [ "pom.xml" ] ) ;
247
+ } else if ( activeBuildTool . toLocaleLowerCase ( ) . includes ( "gradle" ) ) {
248
+ buildFilePath = await this . getBuildFilePathFromNames ( projectPath , [ "build.gradle" , "build.gradle.kts" , "settings.gradle" , "settings.gradle.kts" ] ) ;
249
+ }
250
+ return buildFilePath ;
251
+ } else if ( isMavenEnabled ) {
252
+ return this . getBuildFilePathFromNames ( projectPath , [ "pom.xml" ] ) ;
253
+ } else if ( isGradleEnabled ) {
254
+ return this . getBuildFilePathFromNames ( projectPath , [ "build.gradle" , "build.gradle.kts" , "settings.gradle" , "settings.gradle.kts" ] ) ;
255
+ } else {
256
+ return undefined ;
257
+ }
258
+ }
259
+
260
+ private async getBuildFilePathFromNames ( projectPath : string , buildFileNames : string [ ] ) : Promise < string > {
261
+ for ( const buildFileName of buildFileNames ) {
262
+ const buildFilePath = path . join ( projectPath , buildFileName ) ;
263
+ if ( await fse . pathExists ( buildFilePath ) ) {
264
+ return buildFilePath ;
265
+ }
266
+ }
267
+ return undefined ;
268
+ }
184
269
}
185
270
186
271
interface IProjectInfo {
0 commit comments