-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Coding Guidelines
Anton Kosyakov edited this page Apr 21, 2018
·
48 revisions
Use 4 spaces per indentation
- Use PascalCase for
typenames - Use PascalCase for
enumvalues - Use camelCase for
functionandmethodnames - Use camelCase for
propertynames andlocal variables - Use whole words in names when possible
- Use lower case, dash-separated file names (e.g.
document-provider.ts) - Name files after the main Type it exports
- Add architectural types to the file name separated by a dot. (e.g.
file-navigator.plugin.ts) - Do not use "_" as a prefix for private properties
- Do not export
typesorfunctionsunless you need to share it across multiple components, see as well - Do not introduce new
typesorvaluesto the global namespace
- Do not use I prefix for interfaces.
- Use Impl suffix for implementation of interfaces with the same name.
- See #624 for the discussion on this.
- Use JSDoc style comments for
functions,interfaces,enums, andclasses
- Use "double quotes" for strings shown to the user that need to be externalized (localized)
- Use 'single quotes' otherwise
- All strings visible to the user need to be externalized
Use undefined, do not use null.
- Use arrow functions
=>over anonymous function expressions - Only surround arrow function parameters when necessary. For example,
(x) => x + xis wrong but the following are correct:
x => x + x
(x,y) => x + y
<T>(x: T, y: T) => x === y- Always surround loop and conditional bodies with curly braces
- Open curly braces always go on the same line as whatever necessitates them
- Parenthesized constructs should have no surrounding whitespace. A single space follows commas, colons, and semicolons in those constructs. For example:
for (var i = 0, n = str.length; i < 10; i++) { }
if (x < 10) { }
function f(x: number, y: string): void { }- Use a single declaration per variable statement
(i.e. usevar x = 1; var y = 2;overvar x = 1, y = 2;). -
elsegoes on the line of the closing curly brace.
- 1. Use the property injection over the construction injection. Adding new dependencies via the construction injection is a breaking change.
-
2. Use
postConstructto initialize an object, for example to register event listeners.
@injectable()
export class MyComponent {
@inject(ApplicationShell)
protected readonly shell: ApplicationShell;
@postConstruct()
protected init(): void {
this.shell.activeChanged.connect(() => this.doSomething());
}
}-
3. Make sure to add
inSingletonScopefor singleton instances, otherwise a new instance will be created on each injection request.
// bad
bind(CommandContribution).to(LoggerFrontendContribution);
// good
bind(CommandContribution).to(LoggerFrontendContribution).inSingletonScope();- 4. Don't export functions, convert them into class methods. Functions cannot be overridden to change the behaviour or workaround a bug.
// bad
export function createWebSocket(url: string): WebSocket {
...
}
// good
@injectable()
export class WebSocketProvider {
protected createWebSocket(url: string): WebSocket {
...
}
}
@injectable()
export class MyWebSocketProvider extends WebSocketProvider {
protected createWebSocket(url: string): WebSocket {
// create a web socket with custom options
}
}- 4.1 Convenient functions which are based on the stable API can be exported in the corresponding namespace.
In this case clients:
- can customize behaviour via exchanging the API implementation
- have a choice to use convenient functions or an API directly
export namespace MonacoEditor {
// convenient function to get a Monaco editor based on the editor manager API
export function getCurrent(manager: EditorManager): MonacoEditor | undefined {
return get(manager.currentEditor);
}
...
}JSON types are not supposed to be implementable, but only instantiable. They cannot have functions to avoid serialization issues.
export interface CompositeTreeNode extends TreeNode {
children: ReadonlyArray<TreeNode>;
// bad - json types should not have functions
getFirstChild(): TreeNode | undefined;
}
// good - json types can have corresponding namespaces with functions
export namespace CompositeTreeNode {
export function getFirstChild(parent: CompositeTreeNode): TreeNode | undefined {
return parent.children[0];
}
...
}
// bad - json types should not be implemented
export class MyCompositeTreeNode implements CompositeTreeNode {
...
}
// good - json types can be extended
export interface MyCompositeTreeNode extends CompositeTreeNode {
...
}- 4.3 Auxiliary functions which are called from the customizable context can be exported in the corresponding namespace.
This exception should be used with caution, in cases when an auxilary function does not have any dependencies from the DI context and not supposed to have in future. In such case putting it in the DI context is overkill. Still there should be a clear instantiation point, like a factory method in an injectable class.
@injectable()
export class DirtyDiffModel {
// this method can be overridden, subclasses have an access to `DirtyDiffModel.documentContentLines`
protected handleDocumentChanged(document: TextEditorDocument): void {
this.currentContent = DirtyDiffModel.documentContentLines(document);
this.update();
}
}
export namespace DirtyDiffModel {
// the auxiliary function
export function documentContentLines(document: TextEditorDocument): ContentLines {
...
}
}Project Management
- Roadmap
- Dev Meetings
- Technical Meetings
- Community Call
- Intellectual Property (IP) guide
- Registering CQs (Deprecated)
Documentation