Skip to content
This repository has been archived by the owner on Nov 28, 2022. It is now read-only.

Development Notes

Tim Etchells edited this page Jun 1, 2020 · 1 revision

Codewind for VS Code Development Notes

[email protected]

Start with:

Study:

  • Promises
    • Async/Await and how they are just syntactic sugar for Promises
  • TypeScript (TS)
    • Have some understanding of the tsconfig.json, the TS documentation is generally excellent.
    • Avoid the 'any' type! Everything can be typed.
    • Concepts unfamiliar to Java developers like union (|) and intersection (&) types and the JS Object functions
    • For utility classes, there are some traditional OOP classes with static methods or singleton instances (eg. DebugUtils, ConnectionManager)
      • But more recently I have moved to more JavaScript-style constructs that are just a set of functions in a namespace, maybe with some set-once variables (eg. CLIWrapper)
  • package.json is the 'root' of the extension which then launches extension.ts (extension.js at runtime)
    • https://code.visualstudio.com/api/references/extension-manifest for a rundown of all those values
    • The 'engine' field of package.json determines the minimum VS Code version. Update the documentation and README if you change this.
    • @types/vscode has to match this version exactly (no ~ or ^, see the npm semver note below)

Tasks

  • https://code.visualstudio.com/docs/editor/tasks
  • Dev workflows are built around tasks, which run in the Terminal view. See .vscode/tasks.json
  • The important task is the ts-watch. This is run by default when you run either of the extension launches.
    • Runs tsc (typescript compiler) in watch mode, which incrementally compiles changed files - very fast
    • If an error is encountered the task's Problem Matcher should see it and report it in the Problems view.
      • This doesn't always appear to work with certain warnings - Unused import, parameter, or local variable
  • Generally the tasks for a node project wrap npm scripts. See the 'scripts' section of the package.json

Activation

  • See activationEvents in package.json
  • The opening of the Codewind view is the 'usual' one but the .cw-settings works well if they open a 'codewind-like' workspace

Contributions

  • https://code.visualstudio.com/api/references/contribution-points - done through package.json
    • Any values in the package.json %inPercentSigns% are resolved by the package.nls.json
      • Intended to be used for translation, but for me mostly just used to store enablement expressions (see below)
  • Codewind contributes mostly Commands, as well as the Codewind View and a few Configurations
    • CommandUtil.ts
      • Also see Commands.ts which is just an enum of the values in package.json
        • Would be cool to load package.nls.json and get them from there instead (could be done with tsc --resolveJsonModule or just readFile -> JSON.parse) but I haven't gotten around to it
      • Commands have to be 'registered' into the extension context in TS, see extension.ts / CommandUtil.ts
      • The majority of commands are 'project commands' or 'connection commands' because they need one of those resources to 'run on'
        • If the command is run through the right-click menu, the right-click object (LocalCodewindManager, Project, Connection) is passed to the command handler
        • But if it is run through the command palette, the selection is undefined and the user has to select it
          • See promptForProject/Connection - which is then passed to the command handler
      • See TreeItemContext.ts, package.nls.json and https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts for explanation of the 'when's
        • Commands can be hidden or shown depending on object context, but there are no sub-menus or greying out of actions
        • There is kind of a disconnected duplication here with the TreeItemContext determining action enablement for the right-click menus,
          • but CommandUtil having its own logic for what connections/projects can be selected if using the Command palette
        • Be careful with the command palette because no one seems to use it so it can have hidden problems.
          • Make sure the parameters being passed to the command handler match what the function typedef expects.
    • CodewindTree.ts
      • TreeItemFactory.ts
      • TreeItemContext.ts
    • Configurations.ts

Webviews:

TSConfig:

  • Rarely touched, but totally critical
  • Determines options passed to TypeScript compiler
  • Don't rename this file because VS Code will only look for "tsconfig.json".

TSLint:

Webpack:

  • https://code.visualstudio.com/api/working-with-extensions/bundling-extension
  • The production extension is bundled into a single javascript file dist/extension.js because it loads significantly faster
    • I do not use webpack for development because it resulted in two copies of the code - one in the bundle and one in the regular out/**/*.js which ran separately from each otherr
    • The packager script (see below) replaces the development entrypoint out/extension.js with the prod entrypoint dist/extension.js.
  • Right now the config is relatively straightforward, the above documentation + the webpack documentation should be sufficient.
  • See webpack.config.js and webpack-plugins.js

Packager script vsce-package.js:

  • Should be used instead of running vsce package directly.
  • This is used by the Jenkins build to build two artifacts,
    • The VS Code plugin
    • The Theia plugin which uses a different 'views' section, and removes a series of 'commamnds' which are not supported / applicable in Theia, and also removes the corresponding 'menus' for those commands.
  • It makes some 'production-only' edits to the package.json, runs vsce package, and then restores the package.json to what it was before the packager was run.

Theia/Che:

  • In-Che implies In-Theia, but not vice-versa.
  • Generally, https://github.com/eclipse-theia/theia/issues/created_by/tetchel covers all the things I've had to work around.
  • CWExtensionContext stores the 'is theia' and 'is che' global state and there are a few spots where I check if we're in Theia to avoid these problems.
  • In che, there are a number of rather significant differences
    • not managing the lifecycle of Local Codewind, just making sure it's running through the proxy
    • no restart/debug, lots of other commands are removed by the packager
    • the way project application URLs, and the perf dashboard URL are resolved is totally different
  • Run vsce-package.js "che" to build for che. The regular vsix should work fine in non-che Theia.

Interfacing with Codewind:

  • API calls are done through a project or connection's 'requester' object field which wrap the common logic for making a request 'for a project' or 'for a connection'.
  • Socket events are handled by the MCSocket which should have been renamed to CWSocket by now
  • Cwctl calls are done through CLICommandRunner which in turn calls the CLIWrapper.
  • The cwctl 'lifecycle' commands (which start/stop/remove the local codewind images) are handled in their own file.
  • In general as much as possible is done through cwctl.

Debugging Codewind projects:

  • Create a launch into launch.json which attaches to the project. Updates whenever the attach debugger command is run (which is run as part of the 'restart in debug mode' command).
  • The user can edit or run this launch like any other
    • The extension will overwrite the port, hostname if necessary
    • The extension should not overwrite anything else (if the user adds new properties they should stay)
    • The extension deletes the launch if the project is deleted or disabled
      • Thinking about it now, it should stay if the project is disabled (thought it won't work, there isn't really any need to remove it)

Logging

  • Use the Logger class instead of console.log
    • Log.(d|i|w|e) because it logs more info than console

Translation:

  • See translations/ dir which is resolved by Translator.ts which uses the i18next translation library.
    • https://github.com/microsoft/vscode-nls exists but i18next has named placeholders which was too nice to give up.
      • eg. {{ projectName }} does not have an application {{ podOrContainer }} running.
      • instead of {0} does not have an application {1} running.
  • Only a few strings are translated (left over from the microclimate days)

npm:

Tests:

Look out for:

  • Review the What's New, especially the 'extension authoring' section for new API
  • The workspace reloading when the workspace folders change (see MCUtil.updateWorkspaceFolders for explanation)
  • 'this' in callback functions - MCSocket is a good example of this
  • Don't use the fs.promises API because it's missing in Theia for some reason. Use fs-extra exclusively instead of fs because it has a nicer API that automatically returns a promise if no callback is provided.

The filewatcher:

  • If the filewatcher changed during a release, generally I update it just before DCUT
  • After tagging on the codewind-filewatchers repo, run https://ci.eclipse.org/codewind/job/codewind-filewatchers-tagbuild/ with the new tag added to the "includes" clause in the configuration
    • Joseph knows how to do this
    • Only committer can modify the configuration
  • Then in the VS Code tools, npm uninstall codewind-filewatcher && npm install https://archive.eclipse.org/codewind/codewind-filewatcher-ts/v0.12.0/1/filewatcherd-node_0.11.0.tar.gz
  • You must point to a specific build number, <version>/latest/*.tar.gz will break because npm stores the shasum in the package-lock and will abort the download if it doesn't match the one that was initially installed