function register(languageId, provider) {
        if (!_providers[languageId]) {
            _providers[languageId] = [];
        } else {
            // Check if provider with same name exists for the given language
            // If yes, remove the provider before inserting the most recently loaded one
            var indexOfProvider = _.findIndex(_providers[languageId], function(entry) { return entry.name === provider.name; });
            if (indexOfProvider !== -1) {
                _providers[languageId].splice(indexOfProvider, 1);
            }
        }

        _providers[languageId].push(provider);

        run();  // in case a file of this type is open currently
    }
The provider is passed the text of the file and its fullPath. Providers should not assume
that the file is open (i.e. DocumentManager.getOpenDocumentForPath() may return null) or
that the file on disk matches the text given (file may have unsaved changes).

Registering any provider for the "javascript" language automatically unregisters the built-in
Brackets JSLint provider. This is a temporary convenience until UI exists for disabling
registered providers.

Providers implement scanFile() if results are available synchronously, or scanFileAsync() if results
may require an async wait (if both are implemented, scanFile() is ignored). scanFileAsync() returns
a {$.Promise} object resolved with the same type of value as scanFile() is expected to return.
Rejecting the promise is treated as an internal error in the provider.

@param {string} languageId
@param {{name:string, scanFileAsync:?function(string, string):!{$.Promise},
        scanFile:?function(string, string):?{errors:!Array, aborted:boolean}}} provider

Each error is: { pos:{line,ch}, endPos:?{line,ch}, message:string, type:?Type }
If type is unspecified, Type.WARNING is assumed.
If no errors found, return either null or an object with a zero-length `errors` array.