Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Brackets Coding Conventions

redmunds edited this page Dec 18, 2012 · 29 revisions

Brackets uses some specific coding conventions. All of the pull requests that come in should adhere to the following rules:

Basics

  • Use 4 space indents (spaces, not tabs)

  • All JavaScript files have a single module definition using the following format:

define(function (require, exports, module) {

    // Load dependent modules
    var Module = require("Module");

    function someFunction() {
        // ...
    }

    // Export public APIs
    exports.someFunction = someFunction;
});
  • Must pass JSLint. The default settings for JSLint are:
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */

(With one wrinkle: JSLint warns about lines consisting entirely of whitespace, but we ignore those warnings. The JSLint feature built into Brackets filters out these warnings automatically).

Naming and Syntax


Variable and function names use camelCase (not under_scores): > Do this: > > ``` > var editorHolder; > function getText(); > ``` > > Not this: > > ``` > var editor_holder; // Don't use underscore! > function get_text(); // Don't use underscore! > ```
Use $ prefixes on variables referring to jQuery objects: > Do this: > > ``` > var $sidebar = $("#sidebar"); > ``` > > Not this: > > ``` > var sidebar = $("#sidebar"); // Use '$' to prefix variables referring to jQuery objects > ```
Use _ prefixes on private variables/methods: > Do this: > > ``` > var _privateVar = 42; > function _privateFunction() > ``` > > Not this: > > ``` > var privateVar = 42; // Private vars should start with _ > function privateFunction() // Private functions should start with _ > ```
Classes and id's in HTML use all lower-case with dashes (-), not camelCase or under_scores: > Do this: > > ``` >
> > ``` > > Not this: > > ``` >
// Don't use camel-case for ids > // Don't use underscore > ```
Use semicolons: > Do this: > > ``` > var someVar; > someVar = 2 + 2; > ``` > > Not this: > > ``` > var someVar // Missing semicolon! > someVar = 2 + 2 // Missing semicolon! > ```
Use double quotes in JavaScript. If a JavaScript string literal _contains_ code within it, use single quotes within the string to avoid escaping. > Do this: > > ``` > var aString = "Hello"; > someFunction("This is awesome!"); > > var htmlCode = "
"; > ``` > > Not this: > > ``` > var aString = 'Hello'; // Use double quotes! > someFunction('This is awesome!'); // Use double quotes! > > var htmlCode = '
'; // Use double quotes! > var htmlCode = "
"; // Within string, use single quotes! > ```

Code Structure


Use of Array.forEach() instead of a for loop or $.each(): > Do this: > > ``` > var anArray = [1, 2, 3, 4]; > anArray.forEach(function (value, index) { > // ... > }); > ``` > > Not this: > ``` > var anArray = [1, 2, 3, 4]; > for (var i = 0; i < anArray.length; i++) { // Use Array.forEach() > // ... > } > ``` > > Or this: > ``` > var anArray = [1, 2, 3, 4]; > $.each(anArray, function (index, value) { // Use Array.forEach() > // ... > }) > ```

Prototypal inheritance pattern:

function MyClass() { // constructor
    Parent.call(this); // if this is a subclass
    // ...
}

// the following are only necessary if this is a subclass
MyClass.prototype = Object.create(Parent.prototype);
MyClass.prototype.constructor = MyClass;
MyClass.prototype.parentClass = Parent.prototype;

/**
 * Declare instance variables so we can JSDoc them.
 * @type {string}
 */
MyClass.prototype.myVar = null;

/**
 * @override
 * For override methods, use this pattern for super calls.
 */
MyClass.prototype.myMethod = function (arg1, arg2) {
     // - don't use this.parentClass -- won't work if hierarchy is more than one deep
     // - use apply(this, arguments) instead of call(this, arg1, arg2) so we don't have to fix it up
     //   every time we add a new argument
     MyClass.prototype.parentClass.myMethod.apply(this, arguments);
     // ... 
};

Comments

  • All comments should be C++ single line style //comment.
  • Even multiline comments should use // at the start of each line
  • Use C style /* comments */ for notices at the top and bottom of the file
  • Use JSDoc tags for annotations with Google's Closure Compiler Type Expressions, see https://developers.google.com/closure/compiler/docs/js-for-compiler
  • Annotations should use the /** annotation */
  • Annotate all functions

Exceptions/Asserts/Logging

  • Use exceptions when encountering an unexpected error and recovery is not possible. In other words, the error means that Brackets will be noticeably broken or data could be corrupted if execution continues.
  • Use console.error() or console.assert() when encountering an unexpected error that can be recovered from. In other words, an error occurred and the current operation may not complete successfully, but the overal integrity of the program is not compromised.
  • Use console.log() to note unexpected behavior that is not necessarily an error.

NOTE console.log() should not be used to log general information.

Example 1 - throw and console.log()

The CommandManager.register() function uses console.log() and throw.

console.log() is used to note an unexpected (but not dangerous) condition -- the specified command id has already been registered. The code can continue safely from here.

An exception is thrown if name, id, or commandFn isn't defined. If the code were to continue, a serious consequence is likely to occur -- a menu item could be blank or inoperative, or the command couldn't be mapped by id.

function register(name, id, commandFn) {
    if (_commands[id]) {
        console.log("Attempting to register an already-registered command: " + id);
        return null;
    }
    if (!name || !id || !commandFn) {
         throw new Error("Attempting to register a command with a missing name, id, or command function:" + name + " " + id);
    }

    var command = new Command(name, id, commandFn);
    _commands[id] = command;

    ...
}

Example 2 - console.assert()

In DocumentManager.closeFullEditor(), after opening the next file, we check that the currentDocument property is updated correctly. This is an error if not true, and may lead to unexpected behavior, but it is not catastrophic.

CommandManager.execute(Commands.FILE_OPEN, { fullPath: nextFile.fullPath })
    .done(function () {
        // (Now we're guaranteed that the current document is not the one we're closing)
        console.assert(!(_currentDocument && _currentDocument.file.fullPath === file.fullPath));
    })
Clone this wiki locally