@@ -12,7 +12,7 @@ import { NodeKind } from "../java/nodeData";
12
12
import { DataNode } from "../views/dataNode" ;
13
13
import { resourceRoots } from "../views/packageRootNode" ;
14
14
import { checkJavaQualifiedName } from "./utility" ;
15
- import { sendError , setUserError } from "vscode-extension-telemetry-wrapper" ;
15
+ import { sendError , sendInfo , setUserError } from "vscode-extension-telemetry-wrapper" ;
16
16
17
17
// tslint:disable no-var-requires
18
18
const stringInterpolate = require ( "fmtr" ) ;
@@ -134,7 +134,7 @@ export async function newJavaFile(): Promise<void> {
134
134
return newUntitledJavaFile ( ) ;
135
135
}
136
136
137
- const includeRecord = ! ( await isVersionLessThan ( Uri . file ( packageFsPath ) . toString ( ) , 16 ) ) ;
137
+ const includeRecord = isLanguageServerReady ( ) && ! ( await isVersionLessThan ( Uri . file ( packageFsPath ) . toString ( ) , 16 ) ) ;
138
138
const supportedTypes : string [ ] = JavaType . getDisplayNames ( true , includeRecord ) ;
139
139
const typeName : string | undefined = await window . showQuickPick ( supportedTypes ,
140
140
{
@@ -148,12 +148,18 @@ export async function newJavaFile(): Promise<void> {
148
148
newJavaFile0 ( packageFsPath , JavaType . fromDisplayName ( typeName ) ) ;
149
149
}
150
150
151
- // Create a new Java file from the context menu of Java Projects view.
152
- export async function newJavaFileWithSpecificType ( javaType : JavaType , node ?: DataNode ) : Promise < void > {
151
+ // Create a new Java file from the context menu of Java Projects view or File Explorer.
152
+ export async function newJavaFileWithSpecificType ( javaType : JavaType , node ?: DataNode | Uri ) : Promise < void > {
153
+ sendInfo ( "" , {
154
+ "triggernewfilefrom" : ( node instanceof Uri && node ?. fsPath ) ? "fileExplorer" : "javaProjectExplorer" ,
155
+ "javatype" : javaType . label ,
156
+ } ) ;
153
157
let packageFsPath : string | undefined ;
154
158
if ( ! node ) {
155
159
packageFsPath = await inferPackageFsPath ( ) ;
156
- } else {
160
+ } else if ( node instanceof Uri && node ?. fsPath ) { // File Explorer
161
+ packageFsPath = node ?. fsPath ;
162
+ } else if ( node instanceof DataNode ) { // Java Projects view
157
163
if ( ! node ?. uri || ! canCreateClass ( node ) ) {
158
164
return ;
159
165
}
@@ -292,19 +298,27 @@ async function newUntitledJavaFile(): Promise<void> {
292
298
textEditor . insertSnippet ( new SnippetString ( snippets . join ( "\n" ) ) ) ;
293
299
}
294
300
295
- async function inferPackageFsPath ( ) : Promise < string > {
301
+ function isLanguageServerReady ( ) : boolean {
296
302
const javaLanguageSupport : Extension < any > | undefined = extensions . getExtension ( ExtensionName . JAVA_LANGUAGE_SUPPORT ) ;
297
303
if ( ! javaLanguageSupport || ! javaLanguageSupport . isActive ) {
298
- return "" ;
304
+ return false ;
299
305
}
300
306
301
307
const extensionApi : any = javaLanguageSupport . exports ;
302
308
if ( ! extensionApi ) {
303
- return "" ;
309
+ return false ;
304
310
}
305
311
306
312
if ( extensionApi . serverMode !== "Standard" || extensionApi . status !== "Started" ) {
307
- return "" ;
313
+ return false ;
314
+ }
315
+
316
+ return true ;
317
+ }
318
+
319
+ async function inferPackageFsPath ( ) : Promise < string > {
320
+ if ( ! isLanguageServerReady ( ) ) {
321
+ return getPackageFsPathFromActiveEditor ( ) ;
308
322
}
309
323
310
324
let sourcePaths : string [ ] | undefined ;
@@ -342,6 +356,25 @@ async function inferPackageFsPath(): Promise<string> {
342
356
return "" ;
343
357
}
344
358
359
+ function getPackageFsPathFromActiveEditor ( ) {
360
+ if ( ! window . activeTextEditor ) {
361
+ return "" ;
362
+ }
363
+
364
+ const fileUri : Uri = window . activeTextEditor . document . uri ;
365
+ const workspaceFolder : WorkspaceFolder | undefined = workspace . getWorkspaceFolder ( fileUri ) ;
366
+ if ( ! workspaceFolder ) {
367
+ return "" ;
368
+ }
369
+
370
+ const filePath : string = window . activeTextEditor . document . uri . fsPath ;
371
+ if ( filePath . endsWith ( ".java" ) ) {
372
+ return path . dirname ( filePath ) ;
373
+ }
374
+
375
+ return "" ;
376
+ }
377
+
345
378
function canCreateClass ( node : DataNode ) : boolean {
346
379
if ( node . nodeData . kind === NodeKind . Project ||
347
380
node . nodeData . kind === NodeKind . PackageRoot ||
@@ -383,6 +416,10 @@ async function isVersionLessThan(fileUri: string, targetVersion: number): Promis
383
416
}
384
417
385
418
async function resolvePackageName ( filePath : string ) : Promise < string > {
419
+ if ( ! isLanguageServerReady ( ) ) {
420
+ return guessPackageName ( filePath ) ;
421
+ }
422
+
386
423
let sourcePaths : string [ ] = [ ] ;
387
424
const result : IListCommandResult =
388
425
await commands . executeCommand < IListCommandResult > ( Commands . EXECUTE_WORKSPACE_COMMAND , Commands . LIST_SOURCEPATHS ) ;
@@ -404,6 +441,25 @@ async function resolvePackageName(filePath: string): Promise<string> {
404
441
return "" ;
405
442
}
406
443
444
+ function guessPackageName ( filePath : string ) : string {
445
+ const packagePath : string = path . dirname ( filePath ) ;
446
+ const knownSourcePathPrefixes : string [ ] = [
447
+ "src/main/java/" ,
448
+ "src/test/java/" ,
449
+ "src\\main\\java\\" ,
450
+ "src\\test\\java\\" ,
451
+ ] ;
452
+
453
+ for ( const prefix of knownSourcePathPrefixes ) {
454
+ const index : number = packagePath . lastIndexOf ( prefix ) ;
455
+ if ( index > - 1 ) {
456
+ return packagePath . substring ( index + prefix . length ) . replace ( / [ \\ \/ ] / g, "." ) ;
457
+ }
458
+ }
459
+
460
+ return "" ;
461
+ }
462
+
407
463
function isPrefix ( parentPath : string , filePath : string ) : boolean {
408
464
const relative = path . relative ( parentPath , filePath ) ;
409
465
return ! relative || ( ! relative . startsWith ( '..' ) && ! path . isAbsolute ( relative ) ) ;
0 commit comments