This repository has been archived by the owner on Nov 28, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 30
Development Notes
Tim Etchells edited this page Jun 1, 2020
·
1 revision
- DEVELOPING.md
- dev/src/test/README-Tests.md
- ➡️➡️➡️ https://code.visualstudio.com/api/references/vscode-api ⬅️⬅️⬅️
- Everything under the "references" section is critical
- 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 JSObject
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)
- 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
- 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
-
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)
- Any values in the package.json %inPercentSigns% are resolved by the package.nls.json
- 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.
- Also see Commands.ts which is just an enum of the values in package.json
- CodewindTree.ts
- TreeItemFactory.ts
- TreeItemContext.ts
- Configurations.ts
- CommandUtil.ts
- https://code.visualstudio.com/api/extension-guides/webview
- https://code.visualstudio.com/api/references/theme-color for the list of theme colours you can reference like https://code.visualstudio.com/api/extension-guides/webview#theming-webview-content
- The 'open webview developer tools' command is critical
- My webviews are giant template strings which pass messages back to the extension to execute
- Good because we can directly reference (read) extension code
- Bad because it's just a string so there's no syntax highlighting, checking, etc. Hard to maintain and very hard to share code between pages (see WebviewUtil)
- The command that opens the webview instantiates the WebviewWrapper which passes any info to/from the page and manages its lifecycle
- Also see WebviewUtil.ts
- Webviews should be disposed when the relevant project/connection is disposed (doesn't apply to home page)
- 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".
- Is actually deprecated and supposed to be replaced with eslint, but when I tried to do this there were so many problems I gave up
- I didn't try that hard, but I don't have any issues with my current TSLint setup, so I'm not in any rush.
- https://github.com/palantir/tslint/issues/4534
- https://github.com/typescript-eslint/tslint-to-eslint-config
- 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
- 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.
- 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.
- 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.
- 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)
- Use the Logger class instead of console.log
- Log.(d|i|w|e) because it logs more info than console
- 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.
- eg.
-
https://github.com/microsoft/vscode-nls exists but i18next has named placeholders which was too nice to give up.
- Only a few strings are translated (left over from the microclimate days)
- Know the difference between dependencies and devDependencies
- Use dev dependencies for anything you don't need at runtime
- these are not bundled into the extension so their size doesn't matter
- Know about npm semver and the difference between ^ and ~ and neither
- Know what the package-lock does and what
npm ci
does vsnpm i
- The build uses
npm ci
- https://docs.npmjs.com/cli/ci.html
- The build uses
- Dependencies: https://docs.npmjs.com/specifying-dependencies-and-devdependencies-in-a-package-json-file
- Update all the dependencies once in a while
- Update dev dependencies often - Especially TypeScript should be kept up-to-date since new language features can be so helpful.
- Fairly straightforward, only local at this time but could be extended to make the connection substitutable
- See the readme in src/test
- https://code.visualstudio.com/api/working-with-extensions/testing-extension
- 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. Usefs-extra
exclusively instead offs
because it has a nicer API that automatically returns a promise if no callback is provided.
- 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