Skip to content

Commit

Permalink
finalize
Browse files Browse the repository at this point in the history
  • Loading branch information
CsCherrYY committed Jan 10, 2022
1 parent db5a2f4 commit a58089b
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 97 deletions.
60 changes: 21 additions & 39 deletions extension/src/commands/CreateProjectCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,23 @@ 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 { SelectTestFrameworkStep } from "../createProject/SelectTestFrameworkStep";
import { SpecifyProjectNameStep } from "../createProject/SpecifyProjectNameStep";
import { SpecifySourcePackageNameStep } from "../createProject/SpecifySourcePackageNameStep";
import { IProjectCreationMetadata, IProjectCreationStep, StepResult } from "../createProject/types";
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 {
private selectProjectTypeStep;
private selectScriptDSLStep;
private selectTestFrameworkStep;
private specifyProjectNameStep;
private specifySourcePackageNameStep;

constructor(private client: GradleClient) {
super();
this.selectProjectTypeStep = new SelectProjectTypeStep();
this.selectScriptDSLStep = new SelectScriptDSLStep();
this.selectTestFrameworkStep = new SelectTestFrameworkStep();
this.specifyProjectNameStep = new SpecifyProjectNameStep();
this.specifySourcePackageNameStep = new SpecifySourcePackageNameStep();
}

async run(params: unknown[]): Promise<void> {
if (!params || params[0] === undefined) {
return;
}
const isAdvanced = params[0] as boolean;
const folders = vscode.workspace.workspaceFolders;
const targetFolderUri = await vscode.window.showOpenDialog({
defaultUri: folders && folders.length ? folders[0].uri : undefined,
Expand All @@ -46,24 +31,20 @@ export class CreateProjectCommand extends Command {
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: "java-application",
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 steps: IProjectCreationStep[] = isAdvanced
? [
this.selectProjectTypeStep,
this.selectScriptDSLStep,
this.selectTestFrameworkStep,
this.specifyProjectNameStep,
this.specifySourcePackageNameStep,
]
: [this.selectScriptDSLStep, this.specifyProjectNameStep];
const success = await this.runSteps(steps, metadata);
const success = await this.runSteps(metadata);
if (success) {
await this.createProject(metadata);
const openInNewWindow = !(folders && folders.length);
Expand All @@ -77,20 +58,19 @@ export class CreateProjectCommand extends Command {
return;
}

private async runSteps(steps: IProjectCreationStep[], metadata: IProjectCreationMetadata): Promise<boolean> {
for (let i = 0; i < steps.length; i += 1) {
steps[i].nextStep = steps[i + 1];
steps[i].previousStep = steps[i - 1];
}
let step: IProjectCreationStep | undefined = steps[0];
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 = step.nextStep;
step = metadata.nextStep;
break;
case StepResult.PREVIOUS:
step = step.previousStep;
if (metadata.steps.length === 0) {
return false;
}
step = metadata.steps.pop();
break;
case StepResult.STOP:
return false; // user cancellation
Expand Down Expand Up @@ -118,8 +98,10 @@ export class CreateProjectCommand extends Command {
}
args.push("--project-name");
args.push(metadata.projectName);
args.push("--package");
args.push(metadata.sourcePackageName);
if (metadata.sourcePackageName) {
args.push("--package");
args.push(metadata.sourcePackageName);
}
await this.client.runBuild(metadata.targetFolder, cancellationKey, args);
}
}
27 changes: 13 additions & 14 deletions extension/src/createProject/SelectProjectTypeStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
// Licensed under the MIT license.

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

export class SelectProjectTypeStep implements IProjectCreationStep {
public readonly previousStep?: IProjectCreationStep = undefined;

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";
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;
Expand All @@ -22,21 +23,21 @@ export class SelectProjectTypeStep implements IProjectCreationStep {
const selectedType = pickBox.selectedItems[0];
if (selectedType) {
switch (selectedType.label) {
case "basic":
metadata.projectType = "basic";
break;
case "application":
metadata.projectType = "java-application";
metadata.projectType = ProjectType.JAVA_APPLICATION;
break;
case "library":
metadata.projectType = "java-library";
metadata.projectType = ProjectType.JAVA_LIBRARY;
break;
case "Gradle plugin":
metadata.projectType = "java-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);
}
}),
Expand All @@ -57,10 +58,6 @@ export class SelectProjectTypeStep implements IProjectCreationStep {

private getProjectTypePickItems(): vscode.QuickPickItem[] {
const result: vscode.QuickPickItem[] = [];
result.push({
label: "basic",
description: "A basic, empty, Gradle build",
});
result.push({
label: "application",
description: "A command-line application implemented in Java",
Expand All @@ -76,3 +73,5 @@ export class SelectProjectTypeStep implements IProjectCreationStep {
return result;
}
}

export const selectProjectTypeStep = new SelectProjectTypeStep();
20 changes: 15 additions & 5 deletions extension/src/createProject/SelectScriptDSLStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,24 @@
// Licensed under the MIT license.

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

export class SelectScriptDSLStep implements IProjectCreationStep {
public readonly previousStep?: 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";
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 (this.previousStep) {
if (metadata.steps.length) {
pickBox.buttons = [vscode.QuickInputButtons.Back];
disposables.push(
pickBox.onDidTriggerButton((item) => {
Expand All @@ -41,6 +43,12 @@ export class SelectScriptDSLStep implements IProjectCreationStep {
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);
}
}),
Expand Down Expand Up @@ -70,3 +78,5 @@ export class SelectScriptDSLStep implements IProjectCreationStep {
return result;
}
}

export const selectScriptDSLStep = new SelectScriptDSLStep();
21 changes: 13 additions & 8 deletions extension/src/createProject/SelectTestFrameworkStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@
// Licensed under the MIT license.

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

export class SelectTestFrameworkStep implements IProjectCreationStep {
public readonly previousStep?: IProjectCreationStep;

public async run(metadata: IProjectCreationMetadata): Promise<StepResult> {
const disposables: vscode.Disposable[] = [];
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const selectTestFrameworkPromise = new Promise<StepResult>(async (resolve, _reject) => {
const pickBox = vscode.window.createQuickPick<vscode.QuickPickItem>();
pickBox.title = "Create Gradle Project";
pickBox.title = `Create Gradle project: Select test framework (${metadata.steps.length + 1}/${
metadata.totalSteps
})`;
pickBox.placeholder = "Select test framework ...";
pickBox.matchOnDescription = true;
pickBox.ignoreFocusOut = true;
pickBox.items = this.getTestFrameworkPickItems();
if (this.previousStep) {
if (metadata.steps.length) {
pickBox.buttons = [vscode.QuickInputButtons.Back];
disposables.push(
pickBox.onDidTriggerButton((item) => {
Expand All @@ -37,17 +38,19 @@ export class SelectTestFrameworkStep implements IProjectCreationStep {
metadata.testFramework = undefined;
break;
case "TestNG":
metadata.testFramework = "testng";
metadata.testFramework = TestFramework.TESTNG;
break;
case "Spock":
metadata.testFramework = "spock";
metadata.testFramework = TestFramework.SPOCK;
break;
case "JUnit Jupiter":
metadata.testFramework = "junit-jupiter";
metadata.testFramework = TestFramework.JUNIT_JUPITER;
break;
default:
resolve(StepResult.STOP);
}
metadata.steps.push(selectTestFrameworkStep);
metadata.nextStep = specifyProjectNameStep;
resolve(StepResult.NEXT);
}
}),
Expand Down Expand Up @@ -83,3 +86,5 @@ export class SelectTestFrameworkStep implements IProjectCreationStep {
return result;
}
}

export const selectTestFrameworkStep = new SelectTestFrameworkStep();
16 changes: 12 additions & 4 deletions extension/src/createProject/SpecifyProjectNameStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@
// Licensed under the MIT license.

import * as vscode from "vscode";
import { specifySourcePackageNameStep } from "./SpecifySourcePackageNameStep";
import { IProjectCreationMetadata, IProjectCreationStep, StepResult } from "./types";

export class SpecifyProjectNameStep implements IProjectCreationStep {
public readonly previousStep?: IProjectCreationStep;

public async run(metadata: IProjectCreationMetadata): Promise<StepResult> {
const disposables: vscode.Disposable[] = [];
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const specifyProjectNamePromise = new Promise<StepResult>(async (resolve, _reject) => {
const inputBox = vscode.window.createInputBox();
inputBox.title = "Create Gradle Project";
inputBox.title = `Create Gradle project: Specify project name (${metadata.steps.length + 1}/${
metadata.totalSteps
})`;
inputBox.prompt = "Input name of your project.";
inputBox.placeholder = "e.g. " + metadata.projectName;
inputBox.value = metadata.projectName;
inputBox.ignoreFocusOut = true;
if (this.previousStep) {
const validationMessage: string | undefined = this.isValidProjectName(metadata.projectName);
inputBox.enabled = validationMessage === undefined;
inputBox.validationMessage = validationMessage;
if (metadata.steps.length) {
inputBox.buttons = [vscode.QuickInputButtons.Back];
disposables.push(
inputBox.onDidTriggerButton((item) => {
Expand All @@ -35,6 +39,8 @@ export class SpecifyProjectNameStep implements IProjectCreationStep {
}),
inputBox.onDidAccept(async () => {
metadata.projectName = inputBox.value;
metadata.steps.push(specifyProjectNameStep);
metadata.nextStep = !metadata.isAdvanced ? undefined : specifySourcePackageNameStep;
resolve(StepResult.NEXT);
}),
inputBox.onDidHide(() => {
Expand All @@ -56,3 +62,5 @@ export class SpecifyProjectNameStep implements IProjectCreationStep {
return value.length > 0 ? undefined : "Invalid Project Name.";
}
}

export const specifyProjectNameStep = new SpecifyProjectNameStep();
21 changes: 14 additions & 7 deletions extension/src/createProject/SpecifySourcePackageNameStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@ import * as vscode from "vscode";
import { IProjectCreationMetadata, IProjectCreationStep, StepResult } from "./types";

export class SpecifySourcePackageNameStep implements IProjectCreationStep {
public readonly previousStep?: IProjectCreationStep;

public async run(metadata: IProjectCreationMetadata): Promise<StepResult> {
const disposables: vscode.Disposable[] = [];
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const specifySourcePackageNamePromise = new Promise<StepResult>(async (resolve, _reject) => {
const inputBox = vscode.window.createInputBox();
inputBox.title = "Create Gradle Project";
const defaultName = metadata.sourcePackageName || "";
inputBox.title = `Create Gradle project: Specify package name (${metadata.steps.length + 1}/${
metadata.totalSteps
})`;
inputBox.prompt = "Input source package name of your project.";
inputBox.placeholder = "e.g. " + metadata.sourcePackageName;
inputBox.value = metadata.sourcePackageName;
inputBox.placeholder = "e.g. " + defaultName;
inputBox.value = defaultName;
inputBox.ignoreFocusOut = true;
if (this.previousStep) {
const validationMessage: string | undefined = this.isValidSourcePackageName(defaultName);
inputBox.enabled = validationMessage === undefined;
inputBox.validationMessage = validationMessage;
if (metadata.steps.length) {
inputBox.buttons = [vscode.QuickInputButtons.Back];
disposables.push(
inputBox.onDidTriggerButton((item) => {
Expand All @@ -35,6 +39,7 @@ export class SpecifySourcePackageNameStep implements IProjectCreationStep {
}),
inputBox.onDidAccept(async () => {
metadata.sourcePackageName = inputBox.value;
metadata.nextStep = undefined;
resolve(StepResult.NEXT);
}),
inputBox.onDidHide(() => {
Expand All @@ -53,6 +58,8 @@ export class SpecifySourcePackageNameStep implements IProjectCreationStep {
}

private isValidSourcePackageName(value: string): string | undefined {
return value.length > 0 ? undefined : "Invalid Source Package Name.";
return /^[a-z_][a-z0-9_]*(\.[a-z_][a-z0-9_]*)*$/.test(value) ? undefined : "Invalid Source Package Name.";
}
}

export const specifySourcePackageNameStep = new SpecifySourcePackageNameStep();
Loading

0 comments on commit a58089b

Please sign in to comment.