Skip to content

Commit

Permalink
feat: Add dependency analytics extension recommendation
Browse files Browse the repository at this point in the history
Signed-off-by: Arunprasad Rajkumar <ar.arunprasad@gmail.com>
  • Loading branch information
arajkumar authored and rgrunber committed Jan 28, 2021
1 parent 496e6f3 commit bdacd43
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ExecuteCommandParams, ExecuteCommandRequest, LanguageClient, LanguageCl
import { collectJavaExtensions } from './plugin';
import { prepareExecutable } from './javaServerStarter';
import * as requirements from './requirements';
import { initialize as initializeRecommendation } from './recommendation';
import { Commands } from './commands';
import { ExtensionAPI, ClientStatus } from './extension.api';
import { getJavaConfiguration, deleteDirectory, getBuildFilePatterns, getInclusionPatternsFromNegatedExclusion, convertToGlob, getExclusionBlob } from './utils';
Expand Down Expand Up @@ -127,6 +128,8 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {

enableJavadocSymbols();

initializeRecommendation(context);

return requirements.resolveRequirements(context).catch(error => {
// show error
window.showErrorMessage(error.message, error.label).then((selection) => {
Expand Down
30 changes: 30 additions & 0 deletions src/recommendation/dependencyAnalytics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All rights reserved.

'use strict';

import * as vscode from "vscode";
import { IHandler } from "./handler";

const EXTENSION_NAME = "redhat.fabric8-analytics";
const GH_ORG_URL = `https://github.com/fabric8-analytics`;
const RECOMMENDATION_MESSAGE = `[Dependency Analytics](${GH_ORG_URL}) extension is recommended to get security insights about pom.xml.`;

function isPomDotXml(uri: vscode.Uri) {
return !!uri.path && uri.path.toLowerCase().endsWith("pom.xml");
}

export function initialize (context: vscode.ExtensionContext, handler: IHandler): void {
if (!handler.canRecommendExtension(EXTENSION_NAME)) {
return;
}
context.subscriptions.push(vscode.workspace.onDidOpenTextDocument(e => {
if (isPomDotXml(e.uri)) {
handler.handle(EXTENSION_NAME, RECOMMENDATION_MESSAGE);
}
}));

const isPomDotXmlOpened = vscode.workspace.textDocuments.findIndex(doc => isPomDotXml(doc.uri)) !== -1;
if (isPomDotXmlOpened) {
handler.handle(EXTENSION_NAME, RECOMMENDATION_MESSAGE);
}
}
6 changes: 6 additions & 0 deletions src/recommendation/handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use strict';

export interface IHandler {
handle(extName: string, message: string): Promise<void>;
canRecommendExtension(extName: string): boolean;
}
64 changes: 64 additions & 0 deletions src/recommendation/handlerImpl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) Microsoft Corporation. All rights reserved.

'use strict';

import * as vscode from "vscode";
import { IHandler } from "./handler";

const KEY_RECOMMENDATION_USER_CHOICE_MAP = "recommendationUserChoice";

async function installExtensionCmdHandler(extensionName: string, displayName: string) {
return vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: `Installing ${displayName||extensionName}...`}, progress => {
return vscode.commands.executeCommand("workbench.extensions.installExtension", extensionName);
}).then(() => {
vscode.window.showInformationMessage(`Successfully installed ${displayName||extensionName}.`);
});
}

enum UserChoice {
Install = "Install",
Never = "Never",
Later = "Later",
}

export class HandlerImpl implements IHandler {
userChoice: any;
storeUserChoice: any;
constructor(context: vscode.ExtensionContext) {
this.userChoice = () => {
return context.globalState.get(KEY_RECOMMENDATION_USER_CHOICE_MAP, {});
};

this.storeUserChoice = (choice: object) => {
context.globalState.update(KEY_RECOMMENDATION_USER_CHOICE_MAP, choice);
};
}

isExtensionInstalled(extName: string): boolean {
return !!vscode.extensions.getExtension(extName);
}

canRecommendExtension(extName: string): boolean {
return this.userChoice()[extName] !== UserChoice.Never && !this.isExtensionInstalled(extName);
}

async handle(extName: string, message: string): Promise<void> {
if (this.isExtensionInstalled(extName)) {
return;
}

const choice = this.userChoice();
if (choice[extName] === UserChoice.Never) {
return;
}

const actions: Array<string> = Object.keys(UserChoice);
const answer = await vscode.window.showInformationMessage(message, ...actions);
if (answer === UserChoice.Install) {
await installExtensionCmdHandler(extName, extName);
}

choice[extName] = answer;
this.storeUserChoice(choice);
}
}
12 changes: 12 additions & 0 deletions src/recommendation/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved.

'use strict';

import * as vscode from "vscode";
import { HandlerImpl } from "./handlerImpl";
import { initialize as initDependencyAnalytics } from "./dependencyAnalytics";

export function initialize (context: vscode.ExtensionContext) {
const handler = new HandlerImpl(context);
initDependencyAnalytics(context, handler);
}

0 comments on commit bdacd43

Please sign in to comment.