@@ -12,7 +12,7 @@ import { NodeKind } from "../java/nodeData";
1212import { DataNode } from "../views/dataNode" ;
1313import { resourceRoots } from "../views/packageRootNode" ;
1414import { checkJavaQualifiedName } from "./utility" ;
15- import { sendError , setUserError } from "vscode-extension-telemetry-wrapper" ;
15+ import { sendError , sendInfo , setUserError } from "vscode-extension-telemetry-wrapper" ;
1616
1717// tslint:disable no-var-requires
1818const stringInterpolate = require ( "fmtr" ) ;
@@ -134,7 +134,7 @@ export async function newJavaFile(): Promise<void> {
134134 return newUntitledJavaFile ( ) ;
135135 }
136136
137- const includeRecord = ! ( await isVersionLessThan ( Uri . file ( packageFsPath ) . toString ( ) , 16 ) ) ;
137+ const includeRecord = isLanguageServerReady ( ) && ! ( await isVersionLessThan ( Uri . file ( packageFsPath ) . toString ( ) , 16 ) ) ;
138138 const supportedTypes : string [ ] = JavaType . getDisplayNames ( true , includeRecord ) ;
139139 const typeName : string | undefined = await window . showQuickPick ( supportedTypes ,
140140 {
@@ -148,12 +148,18 @@ export async function newJavaFile(): Promise<void> {
148148 newJavaFile0 ( packageFsPath , JavaType . fromDisplayName ( typeName ) ) ;
149149}
150150
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+ } ) ;
153157 let packageFsPath : string | undefined ;
154158 if ( ! node ) {
155159 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
157163 if ( ! node ?. uri || ! canCreateClass ( node ) ) {
158164 return ;
159165 }
@@ -292,19 +298,27 @@ async function newUntitledJavaFile(): Promise<void> {
292298 textEditor . insertSnippet ( new SnippetString ( snippets . join ( "\n" ) ) ) ;
293299}
294300
295- async function inferPackageFsPath ( ) : Promise < string > {
301+ function isLanguageServerReady ( ) : boolean {
296302 const javaLanguageSupport : Extension < any > | undefined = extensions . getExtension ( ExtensionName . JAVA_LANGUAGE_SUPPORT ) ;
297303 if ( ! javaLanguageSupport || ! javaLanguageSupport . isActive ) {
298- return "" ;
304+ return false ;
299305 }
300306
301307 const extensionApi : any = javaLanguageSupport . exports ;
302308 if ( ! extensionApi ) {
303- return "" ;
309+ return false ;
304310 }
305311
306312 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 ( ) ;
308322 }
309323
310324 let sourcePaths : string [ ] | undefined ;
@@ -342,6 +356,25 @@ async function inferPackageFsPath(): Promise<string> {
342356 return "" ;
343357}
344358
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+
345378function canCreateClass ( node : DataNode ) : boolean {
346379 if ( node . nodeData . kind === NodeKind . Project ||
347380 node . nodeData . kind === NodeKind . PackageRoot ||
@@ -383,6 +416,10 @@ async function isVersionLessThan(fileUri: string, targetVersion: number): Promis
383416}
384417
385418async function resolvePackageName ( filePath : string ) : Promise < string > {
419+ if ( ! isLanguageServerReady ( ) ) {
420+ return guessPackageName ( filePath ) ;
421+ }
422+
386423 let sourcePaths : string [ ] = [ ] ;
387424 const result : IListCommandResult =
388425 await commands . executeCommand < IListCommandResult > ( Commands . EXECUTE_WORKSPACE_COMMAND , Commands . LIST_SOURCEPATHS ) ;
@@ -404,6 +441,25 @@ async function resolvePackageName(filePath: string): Promise<string> {
404441 return "" ;
405442}
406443
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+
407463function isPrefix ( parentPath : string , filePath : string ) : boolean {
408464 const relative = path . relative ( parentPath , filePath ) ;
409465 return ! relative || ( ! relative . startsWith ( '..' ) && ! path . isAbsolute ( relative ) ) ;
0 commit comments