Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add generator for example VS Code extension #155

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
79 changes: 57 additions & 22 deletions src/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ enum ExtensionType {
TreeEditor = 'tree-editor',
Empty = 'empty',
Backend = 'backend',
DiagramEditor = 'diagram-editor'
DiagramEditor = 'diagram-editor',
VsCodeHelloWorld = 'vs-code-hello-world'
}

enum TemplateType {
Expand All @@ -53,6 +54,7 @@ module.exports = class TheiaExtension extends Base {
browser: boolean
electron: boolean
vscode: boolean
plugins: boolean
theiaVersion: string
lernaVersion: string
skipInstall: boolean
Expand Down Expand Up @@ -95,6 +97,12 @@ module.exports = class TheiaExtension extends Base {
type: Boolean,
default: true
})
this.option('plugins', {
alias: 'p',
description: 'Generate plugins folder and extend configs',
type: Boolean,
default: false
})

this.option('author', {
alias: 'a',
Expand Down Expand Up @@ -164,6 +172,7 @@ module.exports = class TheiaExtension extends Base {
message: "The extension's type",
choices: [
{ value: ExtensionType.HelloWorld, name: 'Hello World' },
{ value: ExtensionType.VsCodeHelloWorld, name: 'Hello World (VS Code extension)' },
{ value: ExtensionType.Widget, name: 'Widget (with unit tests)' },
{ value: ExtensionType.LabelProvider, name: 'LabelProvider' },
{ value: ExtensionType.TreeEditor, name: 'TreeEditor' },
Expand All @@ -188,10 +197,10 @@ module.exports = class TheiaExtension extends Base {

(this.options as any).templateType = template;

if(template === TemplateType.Java) {
if (template === TemplateType.Java) {
this.log('\x1b[32m%s\x1b[0m', 'The template will use an EMF source model on the server and generate a Theia extension ✓')
}
if(template === TemplateType.Node) {
if (template === TemplateType.Node) {
this.log('\x1b[32m%s\x1b[0m', 'The template will use a JSON based source model, node as a server and generate a Theia extension ✓')
}
}
Expand All @@ -216,7 +225,7 @@ module.exports = class TheiaExtension extends Base {
let unscopedExtensionName = ''
let extensionPath = ''
let extensionPrefix = ''
if(extensionName) {
if (extensionName) {
unscopedExtensionName = extensionName[0] === '@' ?
extensionName.substring(extensionName.indexOf('/') + 1) :
extensionName;
Expand All @@ -238,8 +247,10 @@ module.exports = class TheiaExtension extends Base {
githubURL,
theiaVersion: options["theia-version"],
lernaVersion: options["lerna-version"],
backend: options["extensionType"] === ExtensionType.Backend
}
backend: options["extensionType"] === ExtensionType.Backend,
includeExtension: options["extensionType"] !== ExtensionType.VsCodeHelloWorld,
includePlugins: options.plugins || options["extensionType"] === ExtensionType.VsCodeHelloWorld,
};
this.params.dependencies = '';
this.params.browserDevDependencies = '';
if (this.params.extensionType === ExtensionType.TreeEditor) {
Expand All @@ -249,7 +260,7 @@ module.exports = class TheiaExtension extends Base {
if (this.params.extensionType === ExtensionType.Widget) {
this.params.devdependencies = `,\n "@testing-library/react": "^11.2.7",\n "@types/jest": "^26.0.20",\n "jest": "^26.6.3",\n "ts-node": "^10.9.1",\n "ts-jest": "^26.5.6"`;
this.params.scripts = `,\n "test": "jest --config configs/jest.config.ts"`;
this.params.rootscripts =`,\n "test": "cd ${this.params.extensionPath} && yarn test"`;
this.params.rootscripts = `,\n "test": "cd ${this.params.extensionPath} && yarn test"`;
this.params.containsTests = true;
}
options.params = this.params
Expand Down Expand Up @@ -298,12 +309,17 @@ module.exports = class TheiaExtension extends Base {
{ params: this.params }
);
}
if (this.params.plugins || this.params.extensionType === ExtensionType.VsCodeHelloWorld) {
this.fs.write('plugins/.gitkeep', 'Folder of VS Code extensions (*.vsix) to be installed by default.');
}
}
if (this.params.extensionType !== ExtensionType.VsCodeHelloWorld) {
this.fs.copyTpl(
this.templatePath('extension-package.json'),
this.extensionPath('package.json'),
{ params: this.params }
);
}
this.fs.copyTpl(
this.templatePath('extension-package.json'),
this.extensionPath('package.json'),
{ params: this.params }
);
this.fs.copyTpl(
this.templatePath('tsconfig.json'),
this.extensionPath('tsconfig.json'),
Expand All @@ -330,6 +346,25 @@ module.exports = class TheiaExtension extends Base {
);
}

/** vs-code-hello-world */
if (this.params.extensionType === ExtensionType.VsCodeHelloWorld) {
this.fs.copyTpl(
this.templatePath('vscode-hello-world/package.json'),
this.extensionPath('package.json'),
{ params: this.params }
);
this.fs.copyTpl(
this.templatePath('vscode-hello-world/gitignore'),
this.extensionPath('.gitignore'),
{ params: this.params }
);
this.fs.copyTpl(
this.templatePath('vscode-hello-world/extension.ts'),
this.extensionPath(`src/extension.ts`),
{ params: this.params }
);
}

/** empty */
if (this.params.extensionType === ExtensionType.Empty) {
this.fs.copyTpl(
Expand Down Expand Up @@ -474,7 +509,7 @@ module.exports = class TheiaExtension extends Base {
if (this.params.extensionType === ExtensionType.DiagramEditor) {
const baseDir = `./glsp-examples-${glspExamplesRepositoryTag}`;
let templatePath = '';
if(this.params.templateType == TemplateType.Java) {
if (this.params.templateType == TemplateType.Java) {
templatePath = '/project-templates/java-emf-theia';
} else if (this.params.templateType == TemplateType.Node) {
templatePath = '/project-templates/node-json-theia';
Expand All @@ -483,9 +518,9 @@ module.exports = class TheiaExtension extends Base {
}

const done = this.async();
request.get(`https://github.com/eclipse-glsp/glsp-examples/archive/refs/tags/${glspExamplesRepositoryTag}.tar.gz`).pipe(tar.x().on('close',() => {
fs.copy(baseDir+'/README.md', './README.md');
fs.copy(baseDir+templatePath, './').then(() => {
request.get(`https://github.com/eclipse-glsp/glsp-examples/archive/refs/tags/${glspExamplesRepositoryTag}.tar.gz`).pipe(tar.x().on('close', () => {
fs.copy(baseDir + '/README.md', './README.md');
fs.copy(baseDir + templatePath, './').then(() => {
fs.rm(baseDir, { recursive: true });
done();
});
Expand All @@ -504,22 +539,22 @@ module.exports = class TheiaExtension extends Base {

const command = this.spawnCommand('yarn', []);

command.on('close', (code:number) => {
if (code === 0 ) {
command.on('close', (code: number) => {
if (code === 0) {
this.log(
'\x1b[32m%s\x1b[0m',
'\nThe DiagramEditor Example has been generated and all dependencies installed\n\nCheck the Readme to get started.'
);
} else {
this.log('\x1b[31m%s\x1b[0m','Command "yarn" failed. Please see above for the reported error message.');
this.log('\x1b[31m%s\x1b[0m', 'Command "yarn" failed. Please see above for the reported error message.');
process.exit(code);
}
});
} else {
const command = this.spawnCommand('yarn', []);
command.on('close', function(code: number){
if (code !== 0 ) {

command.on('close', function (code: number) {
if (code !== 0) {
process.exit(code);
}
})
Expand Down
9 changes: 6 additions & 3 deletions templates/app-browser-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,18 @@
"@theia/preferences": "<%= params.theiaVersion %>",
"@theia/process": "<%= params.theiaVersion %>",
"@theia/terminal": "<%= params.theiaVersion %>",
"@theia/workspace": "<%= params.theiaVersion %>",
"<%= params.extensionName %>": "<%= params.version %>"
"@theia/workspace": "<%= params.theiaVersion %>"<% if (params.includeExtension) { %>,
"<%= params.extensionName %>": "<%= params.version %>"<% } %><% if (params.includePlugins) { %>,
"@theia/plugin": "<%= params.theiaVersion %>",
"@theia/plugin-ext": "<%= params.theiaVersion %>",
"@theia/plugin-ext-vscode": "<%= params.theiaVersion %>"<% } %>
},
"devDependencies": {
"@theia/cli": "<%= params.theiaVersion %>"<% if (params.browserDevDependencies) { %><%- params.browserDevDependencies %><% } %>
},
"scripts": {
"prepare": "theia build --mode development",
"start": "theia start",
"start": "theia start<% if (params.includePlugins) { %> --plugins=local-dir:../plugins<% } %>",
"watch": "theia build --watch --mode development"
},
"theia": {
Expand Down
9 changes: 6 additions & 3 deletions templates/app-electron-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,19 @@
"@theia/preferences": "<%= params.theiaVersion %>",
"@theia/process": "<%= params.theiaVersion %>",
"@theia/terminal": "<%= params.theiaVersion %>",
"@theia/workspace": "<%= params.theiaVersion %>",
"<%= params.extensionName %>": "<%= params.version %>"
"@theia/workspace": "<%= params.theiaVersion %>"<% if (params.includeExtension) { %>,
"<%= params.extensionName %>": "<%= params.version %>"<% } %><% if (params.includePlugins) { %>,
"@theia/plugin": "<%= params.theiaVersion %>",
"@theia/plugin-ext": "<%= params.theiaVersion %>",
"@theia/plugin-ext-vscode": "<%= params.theiaVersion %>"<% } %>
},
"devDependencies": {
"@theia/cli": "<%= params.theiaVersion %>",
"electron": "^15.3.5"
},
"scripts": {
"prepare": "theia build --mode development",
"start": "theia start",
"start": "theia start<% if (params.includePlugins) { %> --plugins=local-dir:../plugins<% } %>",
"watch": "theia build --watch --mode development"
},
"theia": {
Expand Down
12 changes: 8 additions & 4 deletions templates/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
"args": [
"--loglevel=debug",
"--port=3000",
"--no-cluster"
"--no-cluster"<% if (params.includePlugins) { %>,
"--plugins=local-dir:${workspaceRoot}/plugins"<% } %>
],
"env": {
"NODE_ENV": "development"
"NODE_ENV": "development",
"NODE_OPTIONS": "--enable-source-maps"
},
"sourceMaps": true,
"outFiles": [
Expand All @@ -40,10 +42,12 @@
"args": [
"--loglevel=debug",
"--hostname=localhost",
"--no-cluster"
"--no-cluster"<% if (params.includePlugins) { %>,
"--plugins=local-dir:${workspaceRoot}/plugins"<% } %>
],
"env": {
"NODE_ENV": "development"
"NODE_ENV": "development",
"NODE_OPTIONS": "--enable-source-maps"
},
"sourceMaps": true,
"outFiles": [
Expand Down
3 changes: 2 additions & 1 deletion templates/root-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
},
"workspaces": [
"<%= params.extensionPath %>"<% if (params.browser) { %>, "browser-app"<% } %><% if (params.electron) { %>, "electron-app"<% } %>
]
]<% if (params.includePlugins) { %>,
"theiaPluginsDir": "plugins"<% } %>
}
41 changes: 41 additions & 0 deletions templates/vscode-hello-world/extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// The following code is based on
// https://github.com/microsoft/vscode-extension-samples/blob/7b9a0a8c4c631e393862c3e767c7be26bb2233b2/.base-sample/src/extension.ts
// which was published under MIT License (https://github.com/microsoft/vscode-extension-samples/blob/main/LICENSE)
// For more information see https://code.visualstudio.com/api

// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';

// this method is called when your extension is activated
// your extension is activated the very first time the command is executed

/**
* @param {vscode.ExtensionContext} context
*/
function activate(context: vscode.ExtensionContext) {
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
console.log('Congratulations, your extension "<%= params.extensionName %>" is now active!');

// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
let disposable = vscode.commands.registerCommand('<%= params.extensionName %>.helloWorld', () => {
// The code you place here will be executed every time your command is executed

// Display a message box to the user
vscode.window.showInformationMessage('Hello World from a VS Code extension!');
});

context.subscriptions.push(disposable);
}

// this method is called when your extension is deactivated
function deactivate() {}

// eslint-disable-next-line no-undef
module.exports = {
activate,
deactivate
}
Copy link
Member

Choose a reason for hiding this comment

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

minor: newline.

1 change: 1 addition & 0 deletions templates/vscode-hello-world/gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.vsix
Copy link
Member

Choose a reason for hiding this comment

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

minor: newline.

55 changes: 55 additions & 0 deletions templates/vscode-hello-world/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"name": "<%= params.extensionName %>",
"displayName": "Hello World (VS Code extension)",
"engines": {
"vscode": "^1.32.0"
Copy link
Member

Choose a reason for hiding this comment

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

Why are we targetting such an old vscode version, should it not at least match our currently supported api version v1.53.2?

},
"version": "<%= params.version %>",<%
if (params.description) { %>
"description": "<%= params.description %>",
<%} %><%
if (params.author) { %>
"author": "<%= params.author %>",
<% } %><%
if (params.license) { %>
"license": "<%= params.license %>",
<% } %><%
if (params.githubURL) { %>
"repository": {
"type": "git",
"url": "<%= params.githubURL %>.git"
},
"bugs": {
"url": "<%= params.githubURL %>/issues"
},
"homepage": "<%= params.githubURL %>",<% } %>
"categories": [
"Other"
],
"activationEvents": [
"onCommand:<%= params.extensionName %>.helloWorld"
],
"main": "./lib/extension.js",
"contributes": {
"commands": [
{
"command": "<%= params.extensionName %>.helloWorld",
"title": "Hello World (VS Code extension)"
}
]
},
"scripts": {
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"prepare": "yarn run clean && yarn run build && yarn symlink",
"clean": "rimraf lib",
"build": "yarn run compile",
"symlink": "symlink-dir . ../plugins/<%= params.extensionName %>"
},
"devDependencies": {
"@types/vscode": "^1.32.0",
Copy link
Member

Choose a reason for hiding this comment

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

Same as engines.vscode question.

"symlink-dir": "latest",
"rimraf": "latest",
"typescript": "latest"
}
}
Copy link
Member

Choose a reason for hiding this comment

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

minor: newline.