Diff
Modified: trunk/LayoutTests/ChangeLog (141593 => 141594)
--- trunk/LayoutTests/ChangeLog 2013-02-01 15:43:25 UTC (rev 141593)
+++ trunk/LayoutTests/ChangeLog 2013-02-01 15:46:32 UTC (rev 141594)
@@ -1,3 +1,13 @@
+2013-02-01 Pavel Feldman <pfeld...@chromium.org>
+
+ Web Inspector: relax goto file matching again.
+ https://bugs.webkit.org/show_bug.cgi?id=108346
+
+ Reviewed by Vsevolod Vlasov.
+
+ * inspector/filtered-item-selection-dialog-filtering-expected.txt:
+ * inspector/filtered-item-selection-dialog-filtering.html:
+
2013-02-01 Vsevolod Vlasov <vse...@chromium.org>
Web Inspector: Navigator should not create tree elements for uiSourceCodes unless neededm should populate folders on expand only.
Modified: trunk/LayoutTests/inspector/filtered-item-selection-dialog-filtering-expected.txt (141593 => 141594)
--- trunk/LayoutTests/inspector/filtered-item-selection-dialog-filtering-expected.txt 2013-02-01 15:43:25 UTC (rev 141593)
+++ trunk/LayoutTests/inspector/filtered-item-selection-dialog-filtering-expected.txt 2013-02-01 15:46:32 UTC (rev 141594)
@@ -1,75 +1,48 @@
Check to see that FilteredItemSelectionDialog uses proper regex to filter results.
-{
- input : "["a","bc"]"
- output : "["a","bc"]"
- query : ""
- title : "Empty query matches everything"
-}
-{
- input : "["abc","acB"]"
- output : "["acB"]"
- query : "aB"
- title : "Case sensitive matching"
-}
-{
- input : "["abc","bac","a_B"]"
- output : "["abc"]"
- query : "ab"
- title : "Case insensitive matching"
-}
-{
- input : "["div .visible","div . visible "]"
- output : "["div .visible"]"
- query : "d.v "
- title : "Spaces in the input"
-}
-{
- input : "["abab","abaa","caab","baac","fooaab"]"
- output : "["caab","fooaab"]"
- query : "aab"
- title : "Duplicate symbols in query"
-}
-{
- input : "["abab","abaa","caab","baac","fooaab"]"
- output : "["caab","fooaab"]"
- query : "*aab"
- title : "Star in query"
-}
-{
- input : "["abab","abaa","caab","aqb","fooaab"]"
- output : "["caab","aqb","fooaab"]"
- query : "a?b"
- title : "Question in query"
-}
-{
- input : "["^[]{}()\\.$*+?|","0123456789abcdef"]"
- output : "["^[]{}()\\.$*+?|"]"
- query : "^[]{}()\.$*+?|"
- title : "Dangerous input escaping"
-}
-{
- input : "["fooBarBaz","FooBarBaz","Foo_Bar_Baz","foo_bar_baz","foobarbaz","foobarBaz","afooBarBaz","aFooBarBaz","a fooBarBaz","fooBorBaz","fooBorCaz"]"
- output : "["fooBarBaz","afooBarBaz","a fooBarBaz"]"
- query : "fBaB"
- title : "Camel case matching"
-}
-{
- input : "["foOBarBaz","FoOBarBaz","FoO_Bar_Baz","foO_bar_baz","foObarbaz","foObarBaz","afoOBarBaz","aFoOBarBaz","a foOBarBaz","foOBorBaz","foOBorCaz"]"
- output : "["foO_bar_baz"]"
- query : "fO_ba_b"
- title : "Underscore matching"
-}
-{
- input : "["foo_bar","FB","foobar","fBar"]"
- output : "["FB","fBar"]"
- query : "fb"
- title : "Case insensitive matching"
-}
-{
- input : "["foo_bar","FOO_BAR","Foo_Bar","fOo_bAr"]"
- output : "["foo_bar","FOO_BAR","Foo_Bar","fOo_bAr"]"
- query : "f_b"
- title : "Case insensitive underscore matching"
-}
+Empty query matches everything
+Query:""
+Input:["a","bc"]
+Output:["a","bc"]
+
+Case sensitive matching
+Query:"aB"
+Input:["abc","acB"]
+Output:["abc","acB"]
+
+Case insensitive matching
+Query:"ab"
+Input:["abc","bac","a_B"]
+Output:["a_B","abc"]
+
+Duplicate symbols in query
+Query:"aab"
+Input:["abab","abaa","caab","baac","fooaab"]
+Output:["abab","caab","fooaab"]
+
+Dangerous input escaping
+Query:"^[]{}()\\.$*+?|"
+Input:["^[]{}()\\.$*+?|","0123456789abcdef"]
+Output:["^[]{}()\\.$*+?|"]
+
+Camel case matching
+Query:"fBaB"
+Input:["fooBarBaz","FooBarBaz","Foo_Bar_Baz","foo_bar_baz","foobarbaz","foobarBaz","afooBarBaz","aFooBarBaz","a fooBarBaz","fooBorBaz","fooBorCaz"]
+Output:["fooBarBaz","foo_bar_baz","foobarBaz","foobarbaz","FooBarBaz","Foo_Bar_Baz","a fooBarBaz","aFooBarBaz","afooBarBaz"]
+
+Underscore matching
+Query:"fO_ba_b"
+Input:["foOBarBaz","FoOBarBaz","FoO_Bar_Baz","foO_bar_baz","foObarbaz","foObarBaz","afoOBarBaz","aFoOBarBaz","a foOBarBaz","foOBorBaz","foOBorCaz"]
+Output:["foO_bar_baz","FoO_Bar_Baz"]
+
+Case insensitive matching
+Query:"fb"
+Input:["foo_bar","FB","foobar","fBar"]
+Output:["FB","foo_bar","fBar","foobar"]
+
+Case insensitive underscore matching
+Query:"f_b"
+Input:["foo_bar","FOO_BAR","Foo_Bar","fOo_bAr"]
+Output:["Foo_Bar","fOo_bAr","foo_bar","FOO_BAR"]
+
Modified: trunk/LayoutTests/inspector/filtered-item-selection-dialog-filtering.html (141593 => 141594)
--- trunk/LayoutTests/inspector/filtered-item-selection-dialog-filtering.html 2013-02-01 15:43:25 UTC (rev 141593)
+++ trunk/LayoutTests/inspector/filtered-item-selection-dialog-filtering.html 2013-02-01 15:46:32 UTC (rev 141594)
@@ -7,32 +7,40 @@
{
WebInspector.showPanel("scripts");
+ var overridenInput = [];
+ var overridenQuery = "";
+ var delegate = {
+ itemTitleAt: function(itemIndex) { },
+ itemSuffixAt: function(itemIndex) { },
+ itemSubtitleAt: function(itemIndex) { },
+ itemKeyAt: function(itemIndex) { return overridenInput[itemIndex]; },
+ itemsCount: function() { return overridenInput.length; },
+ requestItems: function(callback) { callback(); },
+ selectItem: function(itemIndex, promptValue) { },
+ rewriteQuery: function(query) { return overridenQuery; },
+ };
+
function checkQuery(title, query, input)
{
- var output = [];
- var regex = WebInspector.FilteredItemSelectionDialog.prototype._innerCreateSearchRegExp(query);
+ overridenInput = input;
+ overridenQuery = query;
- for (var i = 0; i < input.length; ++i) {
- var item = input[i];
- if (regex.test(item))
- output.push(item);
- }
+ InspectorTest.addResult("\n" + title);
+ InspectorTest.addResult("Query:" + JSON.stringify(query));
+ InspectorTest.addResult("Input:" + JSON.stringify(input));
- InspectorTest.addObject({
- title: title,
- query: query,
- input: JSON.stringify(input),
- output: JSON.stringify(output)
- });
+ var filteredSelectionDialog = new WebInspector.FilteredItemSelectionDialog(delegate);
+ var items = filteredSelectionDialog._filteredItems;
+ var output = [];
+ for (var i = 0; i < items.length; ++i)
+ output.push(delegate.itemKeyAt(items[i]));
+ InspectorTest.addResult("Output:" + JSON.stringify(output));
}
checkQuery("Empty query matches everything", "", ["a", "bc"]);
checkQuery("Case sensitive matching", "aB", ["abc", "acB"]);
checkQuery("Case insensitive matching", "ab", ["abc", "bac", "a_B"]);
- checkQuery("Spaces in the input", "d.v ", ["div .visible", "div . visible "]);
checkQuery("Duplicate symbols in query", "aab", ["abab", "abaa", "caab", "baac", "fooaab"]);
- checkQuery("Star in query", "*aab", ["abab", "abaa", "caab", "baac", "fooaab"]);
- checkQuery("Question in query", "a?b", ["abab", "abaa", "caab", "aqb", "fooaab"]);
checkQuery("Dangerous input escaping", "^[]{}()\\.$*+?|", ["^[]{}()\\.$*+?|", "0123456789abcdef"]);
checkQuery("Camel case matching", "fBaB", ["fooBarBaz", "FooBarBaz", "Foo_Bar_Baz", "foo_bar_baz", "foobarbaz", "foobarBaz", "afooBarBaz", "aFooBarBaz", "a fooBarBaz", "fooBorBaz", "fooBorCaz"]);
checkQuery("Underscore matching", "fO_ba_b", ["foOBarBaz", "FoOBarBaz", "FoO_Bar_Baz", "foO_bar_baz", "foObarbaz", "foObarBaz", "afoOBarBaz", "aFoOBarBaz", "a foOBarBaz", "foOBorBaz", "foOBorCaz"]);
Modified: trunk/Source/WebCore/ChangeLog (141593 => 141594)
--- trunk/Source/WebCore/ChangeLog 2013-02-01 15:43:25 UTC (rev 141593)
+++ trunk/Source/WebCore/ChangeLog 2013-02-01 15:46:32 UTC (rev 141594)
@@ -1,3 +1,25 @@
+2013-02-01 Pavel Feldman <pfeld...@chromium.org>
+
+ Web Inspector: relax goto file matching again.
+ https://bugs.webkit.org/show_bug.cgi?id=108346
+
+ Reviewed by Vsevolod Vlasov.
+
+ This change brings back behavior introduced in r116244.
+
+ * inspector/front-end/FilteredItemSelectionDialog.js:
+ (WebInspector.FilteredItemSelectionDialog.prototype._createItemElement):
+ (WebInspector.FilteredItemSelectionDialog.prototype._createSearchRegex):
+ (WebInspector.FilteredItemSelectionDialog.prototype._createScoringRegex):
+ (WebInspector.FilteredItemSelectionDialog.prototype._filterItems.compareFunction):
+ (WebInspector.FilteredItemSelectionDialog.prototype._filterItems):
+ (WebInspector.FilteredItemSelectionDialog.prototype._onMouseMove):
+ (WebInspector.FilteredItemSelectionDialog.prototype.itemElement):
+ (WebInspector.OpenResourceDialog):
+ * inspector/front-end/utilities.js:
+ (String.regexSpecialCharacters):
+ (String.prototype.escapeForRegExp):
+
2013-02-01 Vsevolod Vlasov <vse...@chromium.org>
Web Inspector: Navigator should not create tree elements for uiSourceCodes unless neededm should populate folders on expand only.
Modified: trunk/Source/WebCore/inspector/front-end/FilteredItemSelectionDialog.js (141593 => 141594)
--- trunk/Source/WebCore/inspector/front-end/FilteredItemSelectionDialog.js 2013-02-01 15:43:25 UTC (rev 141593)
+++ trunk/Source/WebCore/inspector/front-end/FilteredItemSelectionDialog.js 2013-02-01 15:46:32 UTC (rev 141594)
@@ -157,7 +157,7 @@
var ranges = [];
var match;
if (this._query) {
- var regex = this._createSearchRegExp(this._query, true);
+ var regex = this._createSearchRegex(this._query, true);
while ((match = regex.exec(key)) !== null && match[0])
ranges.push({ offset: match.index, length: regex.lastIndex - match.index });
if (ranges.length)
@@ -170,54 +170,119 @@
},
/**
- * @param {string} query
+ * @param {?string} query
* @param {boolean=} isGlobal
*/
- _createSearchRegExp: function(query, isGlobal)
+ _createSearchRegex: function(query, isGlobal)
{
- return this._innerCreateSearchRegExp(this._delegate.rewriteQuery(query), isGlobal);
+ const toEscape = String.regexSpecialCharacters();
+ var regexString = "";
+ for (var i = 0; i < query.length; ++i) {
+ var c = query.charAt(i);
+ if (toEscape.indexOf(c) !== -1)
+ c = "\\" + c;
+ if (i)
+ regexString += "[^" + c + "]*";
+ regexString += c;
+ }
+ return new RegExp(regexString, "i" + (isGlobal ? "g" : ""));
},
/**
- * @param {?string} query
- * @param {boolean=} isGlobal
+ * @param {string} query
+ * @param {boolean} camelCase
+ * @return {RegExp}
*/
- _innerCreateSearchRegExp: function(query, isGlobal)
+ _createScoringRegex: function(query, camelCase)
{
- if (!query)
- return new RegExp(".*");
- query = query.trim();
-
- var ignoreCase = (query === query.toLowerCase());
- var regExpString = query.escapeForRegExp().replace(/\\\*/g, ".*").replace(/\\\?/g, ".")
- if (ignoreCase)
- regExpString = regExpString.replace(/(?!^)(\\\.|[_:-])/g, "[^._:-]*$1");
- else
- regExpString = regExpString.replace(/(?!^)(\\\.|[A-Z_:-])/g, "[^.A-Z_:-]*$1");
- regExpString = regExpString;
- return new RegExp(regExpString, (ignoreCase ? "i" : "") + (isGlobal ? "g" : ""));
+ query = query.toUpperCase();
+ var regexString = "";
+ for (var i = 0; i < query.length; ++i) {
+ var c = query.charAt(i);
+ if (c < "A" || c > "Z")
+ continue;
+ if (regexString)
+ regexString += camelCase ? "[^A-Z]*" : "[^-_ .]*[-_ .]";
+ regexString += c;
+ }
+ if (!camelCase)
+ regexString = "(?:^|[-_ .])" + regexString;
+ return new RegExp(regexString, camelCase ? "" : "i");
},
_filterItems: function()
{
delete this._filterTimer;
- var query = this._promptElement.value;
- this._query = query.trim();
- var regex = this._createSearchRegExp(query);
+ var query = this._delegate.rewriteQuery(this._promptElement.value.trim());
+ this._query = query;
+ var ignoreCase = (query === query.toLowerCase());
+
+ var filterRegex = query ? this._createSearchRegex(query) : null;
+ var camelCaseScoringRegex = query ? this._createScoringRegex(query, true) : null;
+ var underscoreScoringRegex = query ? this._createScoringRegex(query, false) : null;
+
var oldSelectedAbsoluteIndex = this._filteredItems[this._selectedIndexInFiltered];
this._filteredItems = [];
this._selectedIndexInFiltered = 0;
+
+ var cachedKeys = new Array(this._delegate.itemsCount());
+ var scores = query ? new Array(this._delegate.itemsCount()) : null;
+
for (var i = 0; i < this._delegate.itemsCount(); ++i) {
- var title = this._delegate.itemTitleAt(i);
- if (regex.test(this._delegate.itemKeyAt(i))) {
- if (i === oldSelectedAbsoluteIndex)
- this._selectedIndexInFiltered = this._filteredItems.length;
- this._filteredItems.push(i);
+ var key = this._delegate.itemKeyAt(i);
+ if (filterRegex && !filterRegex.test(key))
+ continue;
+ cachedKeys[i] = key;
+ this._filteredItems.push(i);
+
+ if (!filterRegex)
+ continue;
+
+ var score = 0;
+ if (underscoreScoringRegex.test(key))
+ score += 10;
+ if (camelCaseScoringRegex.test(key))
+ score += ignoreCase ? 10 : 20;
+ for (var j = 0; j < key.length && j < query.length; ++j) {
+ if (key[j] === query[j])
+ score++;
+ if (key[j].toUpperCase() === query[j].toUpperCase())
+ score++;
+ else
+ break;
}
+ scores[i] = score;
}
+ function compareFunction(index1, index2)
+ {
+ if (scores) {
+ var score1 = scores[index1];
+ var score2 = scores[index2];
+ if (score1 > score2)
+ return -1;
+ if (score1 < score2)
+ return 1;
+ }
+ var key1 = cachedKeys[index1];
+ var key2 = cachedKeys[index2];
+ return key1.compareTo(key2);
+ }
+
+ const numberOfItemsToSort = 100;
+ if (this._filteredItems.length > numberOfItemsToSort)
+ this._filteredItems.sortRange(compareFunction.bind(this), 0, this._filteredItems.length - 1, numberOfItemsToSort);
+ else
+ this._filteredItems.sort(compareFunction.bind(this));
+
+ for (var i = 0; i < this._filteredItems.length; ++i) {
+ if (this._filteredItems[i] === oldSelectedAbsoluteIndex) {
+ this._selectedIndexInFiltered = i;
+ break;
+ }
+ }
this._viewportControl.refresh();
this._updateSelection(this._selectedIndexInFiltered);
},
@@ -301,7 +366,7 @@
var itemElement = event.target.enclosingNodeOrSelfWithClass("filtered-item-list-dialog-item");
if (!itemElement)
return;
- this._updateSelection(itemElement._index);
+ this._updateSelection(itemElement._filteredIndex);
},
/**
@@ -319,7 +384,9 @@
itemElement: function(index)
{
var delegateIndex = this._filteredItems[index];
- return this._createItemElement(delegateIndex);
+ var element = this._createItemElement(delegateIndex);
+ element._filteredIndex = index;
+ return element;
},
__proto__: WebInspector.DialogDelegate.prototype
@@ -539,16 +606,6 @@
return !!uiSourceCode.parsedURL.lastPathComponent;
}
this._uiSourceCodes = this._uiSourceCodes.filter(filterOutEmptyURLs);
-
- function compareFunction(uiSourceCode1, uiSourceCode2)
- {
- return uiSourceCode1.parsedURL.lastPathComponent.compareTo(uiSourceCode2.parsedURL.lastPathComponent);
- }
- if (this._uiSourceCodes.length > 1000) {
- this._uiSourceCodes.sortRange(compareFunction, 0, this._uiSourceCodes.length - 1, 1000);
- setTimeout(function() { this._uiSourceCodes.sort(compareFunction); }.bind(this), 0);
- } else
- this._uiSourceCodes.sort(compareFunction);
}
WebInspector.OpenResourceDialog.prototype = {
Modified: trunk/Source/WebCore/inspector/front-end/utilities.js (141593 => 141594)
--- trunk/Source/WebCore/inspector/front-end/utilities.js 2013-02-01 15:43:25 UTC (rev 141593)
+++ trunk/Source/WebCore/inspector/front-end/utilities.js 2013-02-01 15:46:32 UTC (rev 141594)
@@ -94,9 +94,14 @@
return result;
}
+String.regexSpecialCharacters = function()
+{
+ return "^[]{}()\\.$*+?|-,";
+}
+
String.prototype.escapeForRegExp = function()
{
- return this.escapeCharacters("^[]{}()\\.$*+?|");
+ return this.escapeCharacters(String.regexSpecialCharacters);
}
String.prototype.escapeHTML = function()
@@ -643,7 +648,7 @@
function createPlainTextSearchRegex(query, flags)
{
// This should be kept the same as the one in ContentSearchUtils.cpp.
- var regexSpecialCharacters = "[](){}+-*.,?\\^$|";
+ var regexSpecialCharacters = String.regexSpecialCharacters();
var regex = "";
for (var i = 0; i < query.length; ++i) {
var c = query.charAt(i);