Skip to content

Commit

Permalink
support to create new project
Browse files Browse the repository at this point in the history
  • Loading branch information
CsCherrYY committed Jan 10, 2022
1 parent 02ef4b4 commit c8010cf
Show file tree
Hide file tree
Showing 9 changed files with 547 additions and 2 deletions.
18 changes: 18 additions & 0 deletions extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,16 @@
{
"command": "gradle.hideStoppedDaemons",
"title": "Hide Stopped Daemons"
},
{
"command": "gradle.createProject",
"category": "Gradle",
"title": "Create a Gradle Java Project..."
},
{
"command": "gradle.createProjectAdvanced",
"category": "Gradle",
"title": "Create a Gradle Java Project... (Advanced)"
}
],
"menus": {
Expand Down Expand Up @@ -466,6 +476,14 @@
{
"command": "gradle.findTask",
"when": "gradle:extensionActivated"
},
{
"command": "gradle.createProject",
"when": "gradle:extensionActivated"
},
{
"command": "gradle.createProjectAdvanced",
"when": "gradle:extensionActivated"
}
],
"view/title": [
Expand Down
7 changes: 5 additions & 2 deletions extension/src/commands/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ import {
RecentTasksTreeDataProvider,
} from "../views";
import { Command } from "./Command";
import { COMMAND_CREATE_PROJECT, COMMAND_CREATE_PROJECT_ADVANCED, CreateProjectCommand } from "./CreateProjectCommand";
import { HideStoppedDaemonsCommand, HIDE_STOPPED_DAEMONS } from "./HideStoppedDaemonsCommand";
import { ShowStoppedDaemonsCommand, SHOW_STOPPED_DAEMONS } from "./ShowStoppedDaemonsCommand";

Expand All @@ -99,10 +100,10 @@ export class Commands {
private gradleTasksTreeView: vscode.TreeView<vscode.TreeItem>
) {}

private registerCommand(commandId: string, command: Command): void {
private registerCommand(commandId: string, command: Command, params?: unknown[]): void {
this.context.subscriptions.push(
instrumentOperationAsVsCodeCommand(commandId, (...args: unknown[]) => {
return command.run(...args);
return command.run(...args, params || []);
})
);
}
Expand Down Expand Up @@ -180,5 +181,7 @@ export class Commands {
this.registerCommand(COMMAND_FIND_TASK, new FindTaskCommand(this.gradleTasksTreeView, this.gradleTaskProvider));
this.registerCommand(SHOW_STOPPED_DAEMONS, new ShowStoppedDaemonsCommand(this.gradleDaemonsTreeDataProvider));
this.registerCommand(HIDE_STOPPED_DAEMONS, new HideStoppedDaemonsCommand(this.gradleDaemonsTreeDataProvider));
this.registerCommand(COMMAND_CREATE_PROJECT, new CreateProjectCommand(this.client), [false]);
this.registerCommand(COMMAND_CREATE_PROJECT_ADVANCED, new CreateProjectCommand(this.client), [true]);
}
}
107 changes: 107 additions & 0 deletions extension/src/commands/CreateProjectCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

import * as path from "path";
import * as vscode from "vscode";
import { GradleClient } from "../client";
import { getRunTaskCommandCancellationKey } from "../client/CancellationKeys";
import { selectProjectTypeStep } from "../createProject/SelectProjectTypeStep";
import { selectScriptDSLStep } from "../createProject/SelectScriptDSLStep";
import { IProjectCreationMetadata, IProjectCreationStep, ProjectType, StepResult } from "../createProject/types";
import { Command } from "./Command";

export const COMMAND_CREATE_PROJECT = "gradle.createProject";
export const COMMAND_CREATE_PROJECT_ADVANCED = "gradle.createProjectAdvanced";

export class CreateProjectCommand extends Command {
constructor(private client: GradleClient) {
super();
}

async run(params: unknown[]): Promise<void> {
if (!params || params[0] === undefined) {
return;
}
const folders = vscode.workspace.workspaceFolders;
const targetFolderUri = await vscode.window.showOpenDialog({
defaultUri: folders && folders.length ? folders[0].uri : undefined,
title: "Select target Folder",
openLabel: "Select",
canSelectFiles: false,
canSelectFolders: true,
canSelectMany: false,
});
const isAdvanced = params[0] as boolean;
if (targetFolderUri) {
const metadata: IProjectCreationMetadata = {
isAdvanced: isAdvanced,
totalSteps: isAdvanced ? 5 : 2,
testFramework: undefined, // junit4
projectType: ProjectType.JAVA_APPLICATION,
targetFolder: targetFolderUri[0].fsPath,
projectName: path.basename(targetFolderUri[0].fsPath),
sourcePackageName: path.basename(targetFolderUri[0].fsPath),
steps: [],
nextStep: isAdvanced ? selectProjectTypeStep : selectScriptDSLStep,
};
const success = await this.runSteps(metadata);
if (success) {
await this.createProject(metadata);
const openInNewWindow = !(folders && folders.length);
vscode.commands.executeCommand(
"vscode.openFolder",
vscode.Uri.file(metadata.targetFolder),
openInNewWindow
);
}
}
return;
}

private async runSteps(metadata: IProjectCreationMetadata): Promise<boolean> {
let step: IProjectCreationStep | undefined = metadata.nextStep;
while (step !== undefined) {
const result = await step.run(metadata);
switch (result) {
case StepResult.NEXT:
step = metadata.nextStep;
break;
case StepResult.PREVIOUS:
if (metadata.steps.length === 0) {
return false;
}
step = metadata.steps.pop();
break;
case StepResult.STOP:
return false; // user cancellation
default:
throw new Error("invalid StepResult returned.");
}
}
return true;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
private async createProject(metadata: IProjectCreationMetadata): Promise<void> {
const cancellationKey = getRunTaskCommandCancellationKey(metadata.targetFolder, "init");
const args: string[] = ["init"];
if (!metadata.projectType || !metadata.scriptDSL || !metadata.projectName || !metadata.sourcePackageName) {
return;
}
args.push("--dsl");
args.push(metadata.scriptDSL);
args.push("--type");
args.push(metadata.projectType);
if (metadata.testFramework) {
args.push("--test-framework");
args.push(metadata.testFramework);
}
args.push("--project-name");
args.push(metadata.projectName);
if (metadata.sourcePackageName) {
args.push("--package");
args.push(metadata.sourcePackageName);
}
await this.client.runBuild(metadata.targetFolder, cancellationKey, args);
}
}
77 changes: 77 additions & 0 deletions extension/src/createProject/SelectProjectTypeStep.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

import * as vscode from "vscode";
import { selectScriptDSLStep } from "./SelectScriptDSLStep";
import { IProjectCreationMetadata, IProjectCreationStep, ProjectType, StepResult } from "./types";

export class SelectProjectTypeStep implements IProjectCreationStep {
public async run(metadata: IProjectCreationMetadata): Promise<StepResult> {
const disposables: vscode.Disposable[] = [];
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const selectProjectTypePromise = new Promise<StepResult>(async (resolve, _reject) => {
const pickBox = vscode.window.createQuickPick<vscode.QuickPickItem>();
pickBox.title = `Create Gradle project: Select project type (${metadata.steps.length + 1}/${
metadata.totalSteps
})`;
pickBox.placeholder = "Select project type ...";
pickBox.matchOnDescription = true;
pickBox.ignoreFocusOut = true;
pickBox.items = this.getProjectTypePickItems();
disposables.push(
pickBox.onDidAccept(async () => {
const selectedType = pickBox.selectedItems[0];
if (selectedType) {
switch (selectedType.label) {
case "application":
metadata.projectType = ProjectType.JAVA_APPLICATION;
break;
case "library":
metadata.projectType = ProjectType.JAVA_LIBRARY;
break;
case "Gradle plugin":
metadata.projectType = ProjectType.JAVA_GRADLE_PLUGIN;
metadata.totalSteps = 4; // when creating gradle plugin, we shouldn't specify test framework
break;
default:
resolve(StepResult.STOP);
}
metadata.steps.push(selectProjectTypeStep);
metadata.nextStep = selectScriptDSLStep;
resolve(StepResult.NEXT);
}
}),
pickBox.onDidHide(() => {
resolve(StepResult.STOP);
})
);
disposables.push(pickBox);
pickBox.show();
});

try {
return await selectProjectTypePromise;
} finally {
disposables.forEach((d) => d.dispose());
}
}

private getProjectTypePickItems(): vscode.QuickPickItem[] {
const result: vscode.QuickPickItem[] = [];
result.push({
label: "application",
description: "A command-line application implemented in Java",
});
result.push({
label: "library",
description: "A Java library",
});
result.push({
label: "Gradle plugin",
description: "A Gradle plugin implemented in Java",
});
return result;
}
}

export const selectProjectTypeStep = new SelectProjectTypeStep();
82 changes: 82 additions & 0 deletions extension/src/createProject/SelectScriptDSLStep.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

import * as vscode from "vscode";
import { selectTestFrameworkStep } from "./SelectTestFrameworkStep";
import { specifyProjectNameStep } from "./SpecifyProjectNameStep";
import { IProjectCreationMetadata, IProjectCreationStep, ProjectType, StepResult } from "./types";

export class SelectScriptDSLStep implements IProjectCreationStep {
public async run(metadata: IProjectCreationMetadata): Promise<StepResult> {
const disposables: vscode.Disposable[] = [];
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const selectScriptDSLPromise = new Promise<StepResult>(async (resolve, _reject) => {
const pickBox = vscode.window.createQuickPick<vscode.QuickPickItem>();
pickBox.title = `Create Gradle project: Select script DSL (${metadata.steps.length + 1}/${
metadata.totalSteps
})`;
pickBox.placeholder = "Select build script DSL ...";
pickBox.matchOnDescription = true;
pickBox.ignoreFocusOut = true;
pickBox.items = this.getScriptDSLPickItems();
if (metadata.steps.length) {
pickBox.buttons = [vscode.QuickInputButtons.Back];
disposables.push(
pickBox.onDidTriggerButton((item) => {
if (item === vscode.QuickInputButtons.Back) {
resolve(StepResult.PREVIOUS);
}
})
);
}
disposables.push(
pickBox.onDidAccept(() => {
const selectedScriptDSL = pickBox.selectedItems[0];
if (selectedScriptDSL) {
switch (selectedScriptDSL.label) {
case "Groovy":
metadata.scriptDSL = "groovy";
break;
case "Kotlin":
metadata.scriptDSL = "kotlin";
break;
default:
resolve(StepResult.STOP);
}
metadata.steps.push(selectScriptDSLStep);
if (!metadata.isAdvanced || metadata.projectType === ProjectType.JAVA_GRADLE_PLUGIN) {
metadata.nextStep = specifyProjectNameStep;
} else {
metadata.nextStep = selectTestFrameworkStep;
}
resolve(StepResult.NEXT);
}
}),
pickBox.onDidHide(() => {
resolve(StepResult.STOP);
})
);
disposables.push(pickBox);
pickBox.show();
});

try {
return await selectScriptDSLPromise;
} finally {
disposables.forEach((d) => d.dispose());
}
}

private getScriptDSLPickItems(): vscode.QuickPickItem[] {
const result: vscode.QuickPickItem[] = [];
result.push({
label: "Groovy",
});
result.push({
label: "Kotlin",
});
return result;
}
}

export const selectScriptDSLStep = new SelectScriptDSLStep();
Loading

0 comments on commit c8010cf

Please sign in to comment.