Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1900,6 +1900,11 @@
"command": "java.action.copyFullyQualifiedName",
"title": "%java.action.copyFullyQualifiedName%",
"category": "Java"
},
{
"command": "java.jbang.recommend",
"title": "%java.jbang.recommend%",
"category": "Java"
}
],
"keybindings": [
Expand Down
3 changes: 2 additions & 1 deletion package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@
"java.change.searchScope": "Change Search Scope",
"java.action.showExtendedOutline": "Open Extended Outline",
"java.runtimes.add": "Add Java Runtime",
"java.action.copyFullyQualifiedName": "Copy Fully Qualified Name"
"java.action.copyFullyQualifiedName": "Copy Fully Qualified Name",
"java.jbang.recommend": "Recommend JBang"
}
5 changes: 5 additions & 0 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,11 @@ export namespace Commands {
*/
export const COPY_FULLY_QUALIFIED_NAME = 'java.action.copyFullyQualifiedName';
export const GET_FULLY_QUALIFIED_NAME = 'java.getFullyQualifiedName';

/**
* Recommend JBang for single Java file usage.
*/
export const JBANG_RECOMMEND = 'java.jbang.recommend';
}

/**
Expand Down
56 changes: 56 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,15 @@ export async function activate(context: ExtensionContext): Promise<ExtensionAPI>
cleanWorkspaceExists
);

// Recommend JBang when working with a single Java file (issue #3111)
void showJBangRecommendation(context);

context.subscriptions.push(workspace.onDidOpenTextDocument(async (document) => {
if (document.languageId === 'java') {
await showJBangRecommendation(context);
}
}));

return apiManager.getApiInstance();
}

Expand Down Expand Up @@ -1412,3 +1421,50 @@ function addRevealCommand(client: LanguageClient, codeAction: CodeAction, lspEdi
}
return codeAction;
}

const JBANG_RECOMMENDATION_KEY = 'jbangRecommendationShown';
const JBANG_EXTENSION_ID = 'jbangdev.jbang-vscode';
const JBANG_MARKETPLACE_URL = 'https://marketplace.visualstudio.com/items?itemName=jbangdev.jbang-vscode';

function shouldRecommendJBang(): boolean {
// Case 1: No workspace folder (standalone file mode)
if (!workspace.workspaceFolders) {
return true;
}
// Case 2: Workspace folder with just a single Java file
if (workspace.workspaceFolders.length === 1) {
const javaFileCount = workspace.textDocuments.filter(doc => doc.languageId === 'java').length;
if (javaFileCount <= 1) {
return true;
}
}
return false;
}

async function showJBangRecommendation(context: ExtensionContext): Promise<void> {
const alreadyShown = context.globalState.get<boolean>(JBANG_RECOMMENDATION_KEY, false);
if (alreadyShown) {
return;
}

if (!shouldRecommendJBang()) {
return;
}

const install = 'Install JBang';
const maybeLater = 'Maybe Later';
const dontShowAgain = "Don't Show Again";

const choice = await window.showInformationMessage(
'You are working with a single Java file. JBang makes it easy to run Java scripts. Would you like to install the JBang extension?',
install, maybeLater, dontShowAgain
);

if (choice === install) {
await commands.executeCommand(Commands.OPEN_BROWSER, Uri.parse(JBANG_MARKETPLACE_URL));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible to actually install the extension for the user instead of just opening the web browser to the website for the extension. The command for this is "workbench.extensions.installExtension" and it accepts the extension id as an argument.

It's also possible to open the extensions panel and enter the extension ID if you think that's too invasive. However, given the user's clicked "Install" I think it's fine to go ahead and install it.

}

if (choice === dontShowAgain || choice === install) {
await context.globalState.update(JBANG_RECOMMENDATION_KEY, true);
}
}
Loading