Firing up a Task from an extension

Hi,

I’m developing my first Theia extension and am struggling with the documentation (or lack thereof) about running tasks.

I added @theia/task to my Theia project, and described three basic tasks (shell processes running commands) in .theia/tasks.json which ran successfully when started from the command palette.

Next step is to start these tasks from my extension command. I started drafting it up that way:

@injectable()
export class TheiaEmulatorExtensionCommandContribution implements CommandContribution {

    constructor(
        @inject(MessageService) private readonly messageService: MessageService,
        @inject(TaskService) private readonly taskService: TaskService
    ) { }

    registerCommands(registry: CommandRegistry): void {
        registry.registerCommand(TheiaEmulatorExtensionCommand, {
            execute: () => {
                this.taskService.run(???); // not sure about the parameters
                this.messageService.info('Build started.');
            }
        });
    }
}

There I inject the TaskService in order to use its run() method, but I’m not sure about the arguments I should pass there. According to the prototype:

token: number, source: string, taskLabel: string, scope: TaskConfigurationScope

I’m pretty sure I know what my taskLabel is, but that’s about it :slight_smile:

Could someone provide me with any pointer?

Thank you!

Have you tried TaskService#runTask?

1 Like

We try to keep Theia compatible with VS Code. You can also take a look at the VS Code’s Task API here and here for custom tasks.

1 Like

Hi,

I’m back to work this morning and I can’t figure out what’s going on.

I tried to replicate my previous efforts on a new config in order to make sure I didn’t leave anything out in my personal doc. Turns out I probably did.

I added @theia/task as a dependency in my extension’s package.json, in the main folder’s package.json and even in the subfolders (browser-app and electron-app) package.json but every yarn command fails with:

src/browser/theia-websdk-extension-contribution.ts(10,19): error TS2304: Cannot find name 'TaskConfiguration'.
src/browser/theia-websdk-extension-contribution.ts(55,17): error TS2304: Cannot find name 'TaskService'.
src/browser/theia-websdk-extension-contribution.ts(55,60): error TS2304: Cannot find name 'TaskService'.
src/browser/theia-websdk-extension-contribution.ts(55,60): error TS4063: Parameter 'taskService' of constructor from exported class has or is using private name 'TaskService'.

I don’t get what I’m doing wrong. I compared files with my previous work directory and I don’t think I left anything out…

Also, when trying to run the Electron app, I get prompted with this error:

me@ssdk:~/theia-websdk-extension/electron-app$ yarn start /tmp
yarn run v1.22.5
$ theia start /tmp
/home/me/theia-websdk-extension/node_modules/bindings/bindings.js:121
        throw e;
        ^

Error: Module did not self-register: '/home/me/theia-websdk-extension/node_modules/drivelist/build/Release/drivelist.node'.
    at process.func [as dlopen] (electron/js2c/asar.js:140:31)
    at Object.Module._extensions..node (internal/modules/cjs/loader.js:1034:18)
    at Object.func [as .node] (electron/js2c/asar.js:140:31)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Module._load (internal/modules/cjs/loader.js:727:14)
    at Function.Module._load (electron/js2c/asar.js:769:28)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at bindings (/home/me/theia-websdk-extension/node_modules/bindings/bindings.js:112:48)
    at Object.<anonymous> (/home/me/theia-websdk-extension/node_modules/drivelist/js/index.js:25:27)

Any hint? Thanks!

@vincent is theia-websdk your custom extension? Are you sure you are properly binding it in a -module.ts?

Hi @vince-fugnitto, thanks for your answer. I used yo theia-extension to scaffold the repository.
Here is what my theia-websdk-extension/src/browser/theia-websdk-extension-frontend-module.ts looks like:

/**
 * Generated using theia-extension-generator
 */
import { TheiaWebsdkExtensionCommandContribution, TheiaWebsdkExtensionMenuContribution } from './theia-websdk-extension-contribution';
import {
    CommandContribution,
    MenuContribution
} from "@theia/core/lib/common";
import { ContainerModule } from "inversify";

export default new ContainerModule(bind => {
    // add your contribution bindings here
    bind(CommandContribution).to(TheiaWebsdkExtensionCommandContribution);
    bind(MenuContribution).to(TheiaWebsdkExtensionMenuContribution);
});

I just pushed the code there, if you want to take a look. This might make it simpler: https://github.com/khannurien/theia-websdk-extension

@vincent it was a simple error, you were not importing the task types: https://gist.github.com/vince-fugnitto/e8987ec772d6cc1217aeb7b7f2adf750

import { injectable, inject } from "inversify";
import { CommandContribution, CommandRegistry, MenuContribution, MenuModelRegistry, MessageService } from "@theia/core/lib/common";
import { CommonMenus } from "@theia/core/lib/browser";
import { TaskConfiguration } from '@theia/task/lib/common';
import { TaskService } from '@theia/task/lib/browser/task-service';

TaskConfiguration and TaskService were not being imported.

1 Like

What a stupid mistake. Thank you, I still don’t understand how that could have worked in the past. I probably backuped the wrong files.

I still got the following error when trying to open the Electron app, but that’s likely unrelated:

me@ssdk:~/theia-websdk-extension/electron-app$ yarn start /tmp
yarn run v1.22.5
$ theia start /tmp
/home/me/theia-websdk-extension/node_modules/bindings/bindings.js:121
        throw e;
        ^

Error: Module did not self-register: '/home/me/theia-websdk-extension/node_modules/drivelist/build/Release/drivelist.node'.
    at process.func [as dlopen] (electron/js2c/asar.js:140:31)
    at Object.Module._extensions..node (internal/modules/cjs/loader.js:1034:18)
    at Object.func [as .node] (electron/js2c/asar.js:140:31)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Module._load (internal/modules/cjs/loader.js:727:14)
    at Function.Module._load (electron/js2c/asar.js:769:28)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at bindings (/home/me/theia-websdk-extension/node_modules/bindings/bindings.js:112:48)
    at Object.<anonymous> (/home/me/theia-websdk-extension/node_modules/drivelist/js/index.js:25:27)

When I just yarn inside the electron-app folder I get the following warnings:

WARNING in ../node_modules/vscode-textmate/release/main.js 23:15-27
Critical dependency: the request of a dependency is an expression
 @ ../node_modules/@theia/monaco/lib/browser/textmate/monaco-theme-registry.js
 @ ../node_modules/@theia/monaco/lib/browser/monaco-theming-service.js
 @ ../node_modules/@theia/monaco/lib/browser/monaco-frontend-module.js
 @ ../node_modules/@theia/monaco/lib/electron-browser/monaco-electron-module.js
 @ ./src-gen/frontend/index.js

WARNING in ../node_modules/vscode-textmate/release/main.js
Module Warning (from ../node_modules/source-map-loader/index.js):
(Emitted value instead of an instance of Error) Cannot find SourceMap 'main.js.map': Error: Can't resolve './main.js.map' in '/home/me/theia-websdk-extension/node_modules/vscode-textmate/release'
 @ ../node_modules/@theia/monaco/lib/browser/textmate/monaco-theme-registry.js 69:24-50
 @ ../node_modules/@theia/monaco/lib/browser/monaco-theming-service.js
 @ ../node_modules/@theia/monaco/lib/browser/monaco-frontend-module.js
 @ ../node_modules/@theia/monaco/lib/electron-browser/monaco-electron-module.js
 @ ./src-gen/frontend/index.js

@vincent the application started successfully for me, be sure to rebuild the native modules when attempting to run either the browser or electron targets (yarn rebuild:electron).

evinfug@elx7849163z[±|fix-import ✓]:~/Desktop/theia-websdk-extension $ yarn rebuild:electron
yarn run v1.22.4
$ theia rebuild:electron
Processing @theia/node-pty
Processing nsfw
Processing native-keymap
Processing find-git-repositories
Processing drivelist
✔ Rebuild Complete
Done in 14.05s.
evinfug@elx7849163z[±|fix-import ✓]:~/Desktop/theia-websdk-extension $ cd electron-app/
yevinfug@elx7849163z[±|fix-import ✓]:~/Desktop/theia-websdk-extension/electron-app $ yarn start
yarn run v1.22.4
$ theia start
root INFO Theia app listening on http://localhost:35005.
root INFO Configuration directory URI: 'file:///home/evinfug/.theia'
root WARN Frontend CommonFrontendContribution.configure is slow, took: 370.7 ms
root INFO Changed application state from 'init' to 'started_contributions'.
root INFO Changed application state from 'started_contributions' to 'attached_shell'.
root INFO >>> Restoring the layout state...
root INFO <<< Nothing to restore.
root INFO Changed application state from 'attached_shell' to 'initialized_layout'.
root INFO Changed application state from 'initialized_layout' to 'ready'.

Perhaps to make it easier, I’ll add scripts to the generator which for each target does the rebuild and start for you.

I did rebuild:

me@ssdk:~/theia-websdk-extension$ yarn rebuild:electron
yarn run v1.22.5
$ theia rebuild:electron
native node modules are already rebuilt for electron
Done in 0.22s.
me@ssdk:~/theia-websdk-extension$ cd electron-app/
me@ssdk:~/theia-websdk-extension/electron-app$ yarn start
yarn run v1.22.5
$ theia start
/home/me/theia-websdk-extension/node_modules/bindings/bindings.js:121
        throw e;
        ^

Error: Module did not self-register: '/home/me/theia-websdk-extension/node_modules/drivelist/build/Release/drivelist.node'.
    at process.func [as dlopen] (electron/js2c/asar.js:140:31)
    at Object.Module._extensions..node (internal/modules/cjs/loader.js:1034:18)
    at Object.func [as .node] (electron/js2c/asar.js:140:31)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Module._load (internal/modules/cjs/loader.js:727:14)
    at Function.Module._load (electron/js2c/asar.js:769:28)
    at Module.require (internal/modules/cjs/loader.js:852:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at bindings (/home/me/theia-websdk-extension/node_modules/bindings/bindings.js:112:48)
    at Object.<anonymous> (/home/me/theia-websdk-extension/node_modules/drivelist/js/index.js:25:27)

I’ll try and remove every node_modules in the meantime and go again with a clean state.

@vincent try a fresh build, it worked for me when I updated the file to what I sent you. Note that electron needs to be rebuilt to pick up changes as well.

I’ll try and remove every node_modules in the meantime and go again with a clean state.

:+1:

That worked just fine :slight_smile:

Thanks again for your patience.

1 Like

Speaking of runTask; awaiting the method has no effect and I can’t seem to be able to chain tasks. What did I miss? Do I need to look into TaskGraph?

OK, I found Compound Tasks under VS Code API, but had no success within Theia. On my main task, the dependsOn / dependsOrder properties seem to be ignored.

const buildSteps: TaskConfiguration[] = [
    {
        "_scope": TaskScope.Global,
        "label": "Build drivers",
        "type": "shell",
        "command": "echo Build success.",
        "dependsOn": ["Run qmake", "Run make qmake_all", "Run make", "Run make clean"],
        "dependsOrder": DependsOrder.Sequence,
    },
    {
        "_scope": TaskScope.Global,
        "label": "Run qmake",
        "type": "shell",
        "command": "/usr/lib/x86_64-linux-gnu/qt5/bin/qmake",
        "args": [
            "/home/me/git/me_sensorsdk/My_Emulator.pro",
            "-spec",
            "linux-g++",
            "CONFIG+=debug",
            "CONFIG+=qml_debug"
        ],
        "options": {
            "cwd": "/home/me/git/me_sensorsdk"
        }
    },
    {
        "_scope": TaskScope.Global,
        "label": "Run make qmake_all",
        "type": "shell",
        "command": "/usr/bin/make",
        "args": [
            "qmake_all"
        ],
        "options": {
            "cwd": "/home/me/git/me_sensorsdk"
        }
    },
    {
        "_scope": TaskScope.Global,
        "label": "Run make",
        "type": "shell",
        "command": "/usr/bin/make",
        "args": [
            "-j"
        ],
        "options": {
            "cwd": "/home/me/git/me_sensorsdk"
        }
    },
    {
        "_scope": TaskScope.Global,
        "label": "Run make clean",
        "type": "shell",
        "command": "/usr/bin/make",
        "args": [
            "clean"
        ],
        "options": {
            "cwd": "/home/me/git/me_sensorsdk"
        }
    }
];

Then, running this.taskService.runTask(buildSteps[0]); fires up a new Terminal named Task #1 and… that’s it.