Exemple #1
0
    /**
     * Does a set of replacements in a single file on disk.
     * @param {string} fullPath The full path to the file.
     * @param {Object} matchInfo The match info for this file, as returned by `_addSearchMatches()`.
     * @param {string} replaceText The text to replace each result with.
     * @param {boolean=} isRegexp Whether the original query was a regexp.
     * @return {$.Promise} A promise that's resolved when the replacement is finished or rejected with an error if there were one or more errors.
     */
    function _doReplaceOnDisk(fullPath, matchInfo, replaceText, isRegexp) {
        var file = FileSystem.getFileForPath(fullPath);
        return DocumentManager.getDocumentText(file, true).then(function (contents, timestamp, lineEndings) {
            if (timestamp.getTime() !== matchInfo.timestamp.getTime()) {
                // Return a promise that we'll reject immediately. (We can't just return the
                // error since this is the success handler.)
                return new $.Deferred().reject(exports.ERROR_FILE_CHANGED).promise();
            }

            // Note that this assumes that the matches are sorted.
            // TODO: is there a more efficient way to do this in a large string?
            var result = [],
                lastIndex = 0;
            matchInfo.matches.forEach(function (match) {
                if (match.isChecked) {
                    result.push(contents.slice(lastIndex, match.startOffset));
                    result.push(isRegexp ? parseDollars(replaceText, match.result) : replaceText);
                    lastIndex = match.endOffset;
                }
            });
            result.push(contents.slice(lastIndex));

            var newContents = result.join("");
            // TODO: duplicated logic from Document - should refactor this?
            if (lineEndings === FileUtils.LINE_ENDINGS_CRLF) {
                newContents = newContents.replace(/\n/g, "\r\n");
            }

            return Async.promisify(file, "write", newContents);
        });
    }
    /**
     * Runs a file inspection over passed file, specifying a provider is optional.
     * This method doesn't update the Brackets UI, just provides inspection results.
     * These results will reflect any unsaved changes present in the file that is currently opened.
     *
     * @param {!File} file File that will be inspected for errors.
     * @param ?{{name:string, scanFile:function(string, string):?{!errors:Array, aborted:boolean}} provider
     * @return {$.Promise} a jQuery promise that will be resolved with ?{!errors:Array, aborted:boolean}
     */
    function inspectFile(file, provider) {
        var response = new $.Deferred();
        provider = provider || getProviderForPath(file.fullPath);

        if (!provider) {
            response.resolve(null);
            return response.promise();
        }

        DocumentManager.getDocumentText(file)
            .done(function (fileText) {
                var result,
                    perfTimerInspector = PerfUtils.markStart("CodeInspection '" + provider.name + "':\t" + file.fullPath);

                try {
                    result = provider.scanFile(fileText, file.fullPath);
                } catch (err) {
                    console.error("[CodeInspection] Provider " + provider.name + " threw an error: " + err);
                    response.reject(err);
                    return;
                }

                PerfUtils.addMeasurement(perfTimerInspector);
                response.resolve(result);
            })
            .fail(function (err) {
                console.error("[CodeInspection] Could not read file for inspection: " + file.fullPath);
                response.reject(err);
            });

        return response.promise();
    }
Exemple #3
0
 function _doSearchInOneFile(addMatches, file) {
     var result = new $.Deferred();
                 
     if (!_subtreeFilter(file, currentScope)) {
         result.resolve();
     } else {
         DocumentManager.getDocumentText(file)
             .done(function (text) {
                 addMatches(file.fullPath, text, currentQueryExpr);
             })
             .always(function () {
                 // Always resolve. If there is an error, this file
                 // is skipped and we move on to the next file.
                 result.resolve();
             });
     }
     return result.promise();
 }
 /**
  * @private
  * Finds search results in the given file and adds them to 'searchResults.' Resolves with
  * true if any matches found, false if none found. Errors reading the file are treated the
  * same as if no results found.
  * 
  * Does not perform any filtering - assumes caller has already vetted this file as a search
  * candidate.
  * 
  * @param {!File} file
  * @return {$.Promise}
  */
 function _doSearchInOneFile(file) {
     var result = new $.Deferred();
     
     DocumentManager.getDocumentText(file)
         .done(function (text, timestamp) {
             // Note that we don't fire a model change here, since this is always called by some outer batch
             // operation that will fire it once it's done.
             var matches = _getSearchMatches(text, searchModel.queryExpr);
             searchModel.setResults(file.fullPath, {matches: matches, timestamp: timestamp});
             result.resolve(!!matches.length);
         })
         .fail(function () {
             // Always resolve. If there is an error, this file
             // is skipped and we move on to the next file.
             result.resolve(false);
         });
     
     return result.promise();
 }
Exemple #5
0
 Async.doInParallel(fileListResult, function (file) {
     var result = new $.Deferred();
     
     if (!_inScope(file, currentScope)) {
         result.resolve();
     } else {
         DocumentManager.getDocumentText(file)
             .done(function (text) {
                 _addSearchMatches(file.fullPath, text, currentQueryExpr);
                 result.resolve();
             })
             .fail(function (error) {
                 // Always resolve. If there is an error, this file
                 // is skipped and we move on to the next file.
                 result.resolve();
             });
     }
     return result.promise();
 })
Exemple #6
0
    /**
     * Runs a file inspection over passed file. Uses the given list of providers if specified, otherwise uses
     * the set of providers that are registered for the file's language.
     * This method doesn't update the Brackets UI, just provides inspection results.
     * These results will reflect any unsaved changes present in the file if currently open.
     * 
     * The Promise yields an array of provider-result pair objects (the result is the return value of the
     * provider's scanFile() - see register() for details). The result object may be null if there were no
     * errors from that provider.
     * If there are no providers registered for this file, the Promise yields null instead.
     *
     * @param {!File} file File that will be inspected for errors.
     * @param {?Array.<{name:string, scanFile:function(string, string):?{errors:!Array, aborted:boolean}}>} providerList
     * @return {$.Promise} a jQuery promise that will be resolved with ?Array.<{provider:Object, result: ?{errors:!Array, aborted:boolean}}>
     */
    function inspectFile(file, providerList) {
        var response = new $.Deferred(),
            results = [];

        providerList = (providerList || getProvidersForPath(file.fullPath)) || [];

        if (!providerList.length) {
            response.resolve(null);
            return response.promise();
        }

        DocumentManager.getDocumentText(file)
            .done(function (fileText) {
                var perfTimerInspector = PerfUtils.markStart("CodeInspection:\t" + file.fullPath);

                providerList.forEach(function (provider) {
                    var perfTimerProvider = PerfUtils.markStart("CodeInspection '" + provider.name + "':\t" + file.fullPath);

                    try {
                        var scanResult = provider.scanFile(fileText, file.fullPath);
                        results.push({provider: provider, result: scanResult});
                    } catch (err) {
                        console.error("[CodeInspection] Provider " + provider.name + " threw an error: " + err);
                        response.reject(err);
                        return;
                    }

                    PerfUtils.addMeasurement(perfTimerProvider);
                });

                PerfUtils.addMeasurement(perfTimerInspector);

                response.resolve(results);
            })
            .fail(function (err) {
                console.error("[CodeInspection] Could not read file for inspection: " + file.fullPath);
                response.reject(err);
            });

        return response.promise();
    }
Exemple #7
0
    /**
     * Runs a file inspection over passed file. Uses the given list of providers if specified, otherwise uses
     * the set of providers that are registered for the file's language.
     * This method doesn't update the Brackets UI, just provides inspection results.
     * These results will reflect any unsaved changes present in the file if currently open.
     * 
     * The Promise yields an array of provider-result pair objects (the result is the return value of the
     * provider's scanFile() - see register() for details). The result object may be null if there were no
     * errors from that provider.
     * If there are no providers registered for this file, the Promise yields null instead.
     *
     * @param {!File} file File that will be inspected for errors.
     * @param {?Array.<{name:string, scanFileAsync:?function(string, string):!{$.Promise}, scanFile:?function(string, string):?{errors:!Array, aborted:boolean}}>} providerList
     * @return {$.Promise} a jQuery promise that will be resolved with ?Array.<{provider:Object, result: ?{errors:!Array, aborted:boolean}}>
     */
    function inspectFile(file, providerList) {
        var response = new $.Deferred(),
            results = [];

        providerList = (providerList || getProvidersForPath(file.fullPath)) || [];

        if (!providerList.length) {
            response.resolve(null);
            return response.promise();
        }
        
        DocumentManager.getDocumentText(file)
            .done(function (fileText) {
                var perfTimerInspector = PerfUtils.markStart("CodeInspection:\t" + file.fullPath),
                    masterPromise;

                masterPromise = Async.doInParallel(providerList, function (provider) {
                    var perfTimerProvider = PerfUtils.markStart("CodeInspection '" + provider.name + "':\t" + file.fullPath),
                        runPromise = new $.Deferred();
                    
                    runPromise.done(function (scanResult) {
                        results.push({provider: provider, result: scanResult});
                    });
                    
                    if (provider.scanFileAsync) {
                        window.setTimeout(function () {
                            // timeout error
                            var errTimeout = {
                                pos: { line: -1, col: 0},
                                message: StringUtils.format(Strings.LINTER_TIMED_OUT, provider.name, prefs.get(PREF_ASYNC_TIMEOUT)),
                                type: Type.ERROR
                            };
                            runPromise.resolve({errors: [errTimeout]});
                        }, prefs.get(PREF_ASYNC_TIMEOUT));
                        provider.scanFileAsync(fileText, file.fullPath)
                            .done(function (scanResult) {
                                PerfUtils.addMeasurement(perfTimerProvider);
                                runPromise.resolve(scanResult);
                            })
                            .fail(function (err) {
                                var errError = {
                                    pos: {line: -1, col: 0},
                                    message: StringUtils.format(Strings.LINTER_FAILED, provider.name, err),
                                    type: Type.ERROR
                                };
                                console.error("[CodeInspection] Provider " + provider.name + " (async) failed: " + err);
                                runPromise.resolve({errors: [errError]});
                            });
                    } else {
                        try {
                            var scanResult = provider.scanFile(fileText, file.fullPath);
                            PerfUtils.addMeasurement(perfTimerProvider);
                            runPromise.resolve(scanResult);
                        } catch (err) {
                            var errError = {
                                pos: {line: -1, col: 0},
                                message: StringUtils.format(Strings.LINTER_FAILED, provider.name, err),
                                type: Type.ERROR
                            };
                            console.error("[CodeInspection] Provider " + provider.name + " (sync) threw an error: " + err);
                            runPromise.resolve({errors: [errError]});
                        }
                    }
                    return runPromise.promise();

                }, false);
                
                masterPromise.then(function () {
                    // sync async may have pushed results in different order, restore the original order
                    results.sort(function (a, b) {
                        return providerList.indexOf(a.provider) - providerList.indexOf(b.provider);
                    });
                    PerfUtils.addMeasurement(perfTimerInspector);
                    response.resolve(results);
                });

            })
            .fail(function (err) {
                console.error("[CodeInspection] Could not read file for inspection: " + file.fullPath);
                response.reject(err);
            });

        return response.promise();
    }