this.onClickDiv()} />;
}
protected onClickDiv(): void {
// do stuff
}
}
// very bad
class MyWidget extends ReactWidget {
render(): React.ReactNode {
return
;
}
protected onClickDiv(): void {
// do stuff, no `this` access
}
}
// good
class MyWidget extends ReactWidget {
render(): React.ReactNode {
return
}
protected onClickDiv = () => {
// do stuff, can access `this`
}
}
```
## URI/Path
* [1.](#uri-over-path) Pass URIs between frontend and backend, never paths. URIs should be sent as strings in JSON-RPC services, e.g. `RemoteFileSystemServer` accepts strings, not URIs.
> Why? Frontend and backend can have different operating systems leading to incompatibilities between paths. URIs are normalized in order to be OS-agnostic.
* [2.](#frontend-fs-path) Use `FileService.fsPath` to get a path on the frontend from a URI.
* [3.](#backend-fs-path) Use `FileUri.fsPath` to get a path on the backend from a URI. Never use it on the frontend.
* [4.](#explicit-uri-scheme) Always define an explicit scheme for a URI.
> Why? A URI without scheme will fall back to `file` scheme for now; in the future it will lead to a runtime error.
* [5.](#frontend-path) Use `Path` Theia API to manipulate paths on the frontend. Don't use Node.js APIs like `path` module. Also see [the code organization guideline](code-organization.md).
* [6.](#backend-fs) On the backend, use Node.js APIS to manipulate the file system, like `fs` and `fs-extra` modules.
> Why? `FileService` is to expose file system capabilities to the frontend only. It's aligned with expectations and requirements on the frontend. Using it on the backend is not possible.
* [7.](#use-long-name) Use `LabelProvider.getLongName(uri)` to get a system-wide human-readable representation of a full path. Don't use `uri.toString()` or `uri.path.toString()`.
* [8.](#use-short-name) Use `LabelProvider.getName(uri)` to get a system-wide human-readable representation of a simple file name.
* [9.](#use-icon) Use `LabelProvider.getIcon(uri)` to get a system-wide file icon.
* [10.](#uri-no-string-manipulation) Don't use `string` to manipulate URIs and paths. Use `URI` and `Path` capabilities instead, like `join`, `resolve` and `relative`.
> Why? Because object representation can handle corner cases properly, like trailing separators.
```ts
// bad
uriString + '/' + pathString
// good
new URI(uriString).join(pathString)
// bad
pathString.substring(absolutePathString.length + 1)
// good
new Path(absolutePathString).relative(pathString)
```
## Logging
* [1.](#logging-use-console-log) Use `console` instead of `ILogger` for the root (top-level) logging.
```ts
// bad
@inject(ILogger)
protected readonly logger: ILogger;
this.logger.info(``);
// good
console.info(``)
```
> Why? All calls to console are intercepted on the frontend and backend and then forwarded to an `ILogger` instance already. The log level can be configured from the CLI: `theia start --log-level=debug`.
## "To Do" Tags
There are situations where we can't properly implement some functionality at the time we merge a PR. In those cases, it is sometimes good practice to leave an indication that something needs to be fixed later in the code. This can be done by putting a "tag" string in a comment. This allows us to find the places we need to fix again later. Currently, we use two "standard" tags in Theia:
* `@stubbed`
This tag is used in VS Code API implementations. Sometimes we need an implementation of an API in order for VS Code extensions to start up correctly, but we can't provide a proper implementation of the underlying feature at this time. This might be because a certain feature has no corresponding UI in Theia or because we do not have the resources to provide a proper implementation.
Using the `@stubbed` tag in a JSDoc comment will mark the element as "stubbed" on the [API status page](https://eclipse-theia.github.io/vscode-theia-comparator/status.html)
* `@monaco-uplift`
Use this tag when some functionality can be added or needs to be fixed when we move to a newer version of the monaco editor. If you know which minimum version of Monaco we need, you can add that as a reminder.