diff --git a/src/search/QuickOpen.js b/src/search/QuickOpen.js index 358bded1342..094f024a872 100644 --- a/src/search/QuickOpen.js +++ b/src/search/QuickOpen.js @@ -390,9 +390,10 @@ define(function (require, exports, module) { * list items are re-rendered. Both happen synchronously just after we return. Called even when results is empty. */ QuickNavigateDialog.prototype._handleResultsReady = function (e, results) { - // Give visual clue when there are no results - var isNoResults = (results.length === 0 && !this._isValidLineNumberQuery(this.$searchField.val())); - this.$searchField.toggleClass("no-results", isNoResults); + // Give visual clue when there are no results (unless we're in "Go To Line" mode, where there + // are never results, or we're in file search mode and waiting for the index to get rebuilt) + var isNoResults = (results.length === 0 && (fileList || currentPlugin) && !this._isValidLineNumberQuery(this.$searchField.val())); + this.$searchField.toggleClass("no-results", Boolean(isNoResults)); }; /** @@ -786,12 +787,12 @@ define(function (require, exports, module) { // Start fetching the file list, which will be needed the first time the user enters an un-prefixed query. If FileIndexManager's // caches are out of date, this list might take some time to asynchronously build. See searchFileList() for how this is handled. - fileList = null; fileListPromise = FileIndexManager.getFileInfoList("all") .done(function (files) { fileList = files; fileListPromise = null; - }); + this._filenameMatcher.reset(); + }.bind(this)); }; function getCurrentEditorSelectedText() { @@ -833,8 +834,11 @@ define(function (require, exports, module) { beginSearch("@", getCurrentEditorSelectedText()); } } - - + + // Listen for a change of project to invalidate our file list + $(ProjectManager).on("projectOpen", function () { + fileList = null; + }); // TODO: allow QuickOpenJS to register it's own commands and key bindings CommandManager.register(Strings.CMD_QUICK_OPEN, Commands.NAVIGATE_QUICK_OPEN, doFileSearch); diff --git a/src/utils/StringMatch.js b/src/utils/StringMatch.js index 760dbdd382f..f8b282189b7 100644 --- a/src/utils/StringMatch.js +++ b/src/utils/StringMatch.js @@ -761,11 +761,7 @@ define(function (require, exports, module) { * (This object's caches are all stored in "_" prefixed properties.) */ function StringMatcher() { - // We keep track of the last query to know when we need to invalidate. - this._lastQuery = null; - - this._specialsCache = {}; - this._noMatchCache = {}; + this.reset(); } /** @@ -782,6 +778,17 @@ define(function (require, exports, module) { */ StringMatcher.prototype._noMatchCache = null; + /** + * Clears the caches. Use this in the event that the caches may be invalid. + */ + StringMatcher.prototype.reset = function () { + // We keep track of the last query to know when we need to invalidate. + this._lastQuery = null; + + this._specialsCache = {}; + this._noMatchCache = {}; + }; + /** * Performs a single match using the stringMatch function. See stringMatch for full documentation. * diff --git a/test/spec/StringMatch-test.js b/test/spec/StringMatch-test.js index 89eee836375..a6236d2b05f 100644 --- a/test/spec/StringMatch-test.js +++ b/test/spec/StringMatch-test.js @@ -594,7 +594,7 @@ define(function (require, exports, module) { }); describe("StringMatcher", function () { - it("should manage its caches properly", function () { + beforeEach(function () { this.addMatchers({ toBeInCache: function (matcher, cacheName) { var value = matcher[cacheName][this.actual]; @@ -607,7 +607,9 @@ define(function (require, exports, module) { return value !== undefined; } }); - + }); + + it("should manage its caches properly", function () { var matcher = new StringMatch.StringMatcher(); expect(matcher._noMatchCache).toEqual({}); expect(matcher._specialsCache).toEqual({}); @@ -642,6 +644,16 @@ define(function (require, exports, module) { var lengthResult = matcher.match("length", "l"); expect(lengthResult).toBeTruthy(); }); + + it("can reset the caches", function () { + var matcher = new StringMatch.StringMatcher(); + matcher.match("foo", "spec/live"); + expect("foo").toBeInCache(matcher, "_specialsCache"); + expect("foo").toBeInCache(matcher, "_noMatchCache"); + matcher.reset(); + expect("foo").not.toBeInCache(matcher, "_specialsCache"); + expect("foo").not.toBeInCache(matcher, "_noMatchCache"); + }); }); }); });