Title: [141594] trunk
Revision
141594
Author
pfeld...@chromium.org
Date
2013-02-01 07:46:32 -0800 (Fri, 01 Feb 2013)

Log Message

Web Inspector: relax goto file matching again.
https://bugs.webkit.org/show_bug.cgi?id=108346

Reviewed by Vsevolod Vlasov.

Source/WebCore:

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):

LayoutTests:

* inspector/filtered-item-selection-dialog-filtering-expected.txt:
* inspector/filtered-item-selection-dialog-filtering.html:

Modified Paths

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);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to