feat: support user defined templates (#81)

This commit is contained in:
Eric Chen 2020-09-18 09:06:19 +08:00 коммит произвёл GitHub
Родитель 14313c3697
Коммит f2bc7918b4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
10 изменённых файлов: 36 добавлений и 30 удалений

Просмотреть файл

@ -40,7 +40,7 @@
"jsonValidation": [
{
"fileMatch": "*.json",
"url": "./resources/templates/emptySchema.json"
"url": "./resources/jsonSchema.json"
}
],
"languages": [

Просмотреть файл

Просмотреть файл

@ -9,9 +9,8 @@ export class Constants {
public static readonly UTF8 = "utf8";
public static readonly EMPTY_STRING = "";
public static readonly JSON_SPACE = 2;
public static readonly RESOURCE_FOLDER = "resources";
public static readonly TEMPLATE_FOLDER = "templates";
public static readonly SAMPLE_FILE_NAME = "sample";
public static readonly TEMPLATE_FILE_GLOB = "**/*.json";
public static readonly DTDL_LANGUAGE_SERVER_ID = "dtdl-language-server";
public static readonly DTDL_LANGUAGE_SERVER_NAME = "DTDL Language Server";
public static readonly DTDL_LANGUAGE_SERVER_RELATIVE_PATH = "dist/main.js";

Просмотреть файл

@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import * as glob from "glob";
import * as fs from "fs-extra";
import * as path from "path";
import { DeviceModelManager, ModelType } from "../deviceModel/deviceModelManager";
@ -48,12 +49,11 @@ export class Utility {
}
/**
* get json content from file
* @param filePath file path
* list file in folder
* @param folder folder path
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public static async getJsonContent(filePath: string): Promise<any> {
return fs.readJson(filePath, { encoding: Constants.UTF8 });
public static listFile(folder: string, filePattern: string): string[] {
return glob.sync(filePattern, { cwd: folder });
}
/**

Просмотреть файл

@ -26,7 +26,7 @@ export class DeviceModelManager {
* @param name model name
*/
public static generateModelId(name: string): string {
return `dtmi:{company}:${name};1`;
return `dtmi:com:example:${name};1`;
}
/**
@ -38,14 +38,6 @@ export class DeviceModelManager {
return `${name}.json`;
}
/**
* get DigitalTwin template file name
* @param type model type
*/
public static getTemplateFileName(): string {
return DeviceModelManager.generateModelFileName(Constants.SAMPLE_FILE_NAME);
}
private readonly component: string;
constructor(private readonly context: vscode.ExtensionContext, private readonly outputChannel: ColorizedChannel) {
this.component = Constants.DEVICE_MODEL_COMPONENT;
@ -58,12 +50,14 @@ export class DeviceModelManager {
public async createModel(type: ModelType): Promise<void> {
const folder: string = await UI.selectRootFolder(UIConstants.SELECT_ROOT_FOLDER_LABEL);
const name: string = await UI.inputModelName(UIConstants.INPUT_MODEL_NAME_LABEL, type, folder);
const operation = `Create ${type} ${name} in folder ${folder}`;
const templateFolder: string = this.context.asAbsolutePath(path.join(Constants.TEMPLATE_FOLDER));
const template: string = await UI.selectTemplateFile(UIConstants.SELECT_TEMPLATE_FILE_LABEL, templateFolder);
const operation = `Create ${type} "${name}" in folder ${folder} by template "${template}"`;
this.outputChannel.start(operation, this.component);
let filePath: string;
try {
filePath = await this.doCreateModel(folder, name);
filePath = await this.doCreateModel(folder, name, path.join(templateFolder, template));
} catch (error) {
throw new ProcessError(operation, error, this.component);
}
@ -75,16 +69,13 @@ export class DeviceModelManager {
/**
* create DigitalTwin model
* @param type model type
* @param folder root folder
* @param name model name
* @param templatePath template file path
*/
private async doCreateModel(folder: string, name: string): Promise<string> {
private async doCreateModel(folder: string, name: string, templatePath: string): Promise<string> {
const modelId: string = DeviceModelManager.generateModelId(name);
const filePath: string = path.join(folder, DeviceModelManager.generateModelFileName(name));
const templatePath: string = this.context.asAbsolutePath(
path.join(Constants.RESOURCE_FOLDER, Constants.TEMPLATE_FOLDER, DeviceModelManager.getTemplateFileName())
);
const replacement = new Map<string, string>();
replacement.set(Constants.MODEL_ID_PLACEHOLDER, modelId);
replacement.set(Constants.MODEL_NAME_PLACEHOLDER, name);

Просмотреть файл

@ -18,12 +18,14 @@ jest.mock("../view/ui");
describe("Device model manager", () => {
const folder = "root";
const template = "template";
const context = vscode.ExtensionContext;
const channel = new ColorizedChannel(Constants.CHANNEL_NAME);
const manager = new DeviceModelManager(context, channel);
UI.selectRootFolder = jest.fn().mockResolvedValue(folder);
UI.inputModelName = jest.fn().mockResolvedValue("test");
UI.selectTemplateFile = jest.fn().mockResolvedValue(template);
test("create interface successfully", async () => {
await manager.createModel(ModelType.Interface);

Просмотреть файл

@ -1,6 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
test("1 + 1 = 2", () => {
expect(1 + 1).toEqual(2);
});

Просмотреть файл

@ -78,6 +78,25 @@ export class UI {
return selected.description || (await UI.showOpenDialog(label));
}
/**
* select template file
* @param label label
* @param folder template folder
*/
public static async selectTemplateFile(label: string, folder: string): Promise<string> {
const files: string[] = Utility.listFile(folder, Constants.TEMPLATE_FILE_GLOB);
if (files.length === 1) {
return files[0];
}
const items: vscode.QuickPickItem[] = files.map(file => {
return {
label: file
};
});
const selected: vscode.QuickPickItem = await UI.showQuickPick(label, items);
return selected.label;
}
/**
* input model name and validate
* @param label label

Просмотреть файл

@ -6,6 +6,7 @@
*/
export class UIConstants {
public static readonly SELECT_ROOT_FOLDER_LABEL = "Select folder";
public static readonly SELECT_TEMPLATE_FILE_LABEL = "Select template file";
public static readonly INPUT_MODEL_NAME_LABEL = "Input device model name";
public static readonly BROWSE_LABEL = "Browse...";
}

Просмотреть файл