Web Inspector: [Styles] Retain selector case as written in the source code
authorapavlov@chromium.org <apavlov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Dec 2012 08:51:07 +0000 (08:51 +0000)
committerapavlov@chromium.org <apavlov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 3 Dec 2012 08:51:07 +0000 (08:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=103118

Reviewed by Antti Koivisto.

Source/WebCore:

This change:
- adds parsing of selector group components in the CSSParser;
- builds the SelectorList.selectors based on the source code whenever possible.
  Strips [multiline] comments and whitespace;
- adds the MultilineMode to RegularExpression.

Test: inspector/styles/selector-list.html

* WebCore.exp.in: Update the exported symbol.
* css/CSSGrammar.y.in: Add invocations for CSSParser::markSelector[Start|End]() as required.
* css/CSSParser.cpp:
(WebCore::CSSParser::markSelectorStart): Gets invoked to mark a selector group item start offset.
(WebCore::CSSParser::markSelectorEnd): Ditto for the end offset.
* css/CSSParser.h: Add new methods and a SourceRange tracking field.
* css/CSSPropertySourceData.h: Add SelectorRangeList to the CSSRuleSourceData.
* inspector/InspectorStyleSheet.cpp:
(WebCore::selectorsFromSource): Builds the SelectorList based on the underlying source data.
Strips comments and whitespace from selectors.
(WebCore::InspectorStyleSheet::buildObjectForSelectorList):
Builds SelectorList based on the availability of the source code.
* inspector/front-end/StylesSidebarPane.js:
(WebInspector.StylePropertiesSection.prototype._markSelectorMatches):
Update selectors in all cases to make use of the source-based information whenever possible.
* platform/text/RegularExpression.cpp:
Add the MultilineMode parameter into the constructor/factory method and ultimately pass it into YarrPattern.
(WebCore::RegularExpression::Private::create): See above.
(WebCore::RegularExpression::Private::Private): See above.
(WebCore::RegularExpression::Private::compile): See above.
(WebCore::RegularExpression::RegularExpression): See above.
* platform/text/RegularExpression.h:
Add enum MultilineMode, modify constructor and factory method signatures accordingly.

LayoutTests:

* inspector/styles/selector-list-expected.txt: Added.
* inspector/styles/selector-list.html: Added.
* inspector/styles/styles-add-new-rule-expected.txt: Rebaselined.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@136370 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/styles/selector-list-expected.txt [new file with mode: 0644]
LayoutTests/inspector/styles/selector-list.html [new file with mode: 0644]
LayoutTests/inspector/styles/styles-add-new-rule-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/css/CSSGrammar.y.in
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/CSSParser.h
Source/WebCore/css/CSSPropertySourceData.h
Source/WebCore/inspector/InspectorStyleSheet.cpp
Source/WebCore/inspector/front-end/StylesSidebarPane.js
Source/WebCore/platform/text/RegularExpression.cpp
Source/WebCore/platform/text/RegularExpression.h

index 5288acc..8f1d6c7 100644 (file)
@@ -1,3 +1,14 @@
+2012-12-03  Alexander Pavlov  <apavlov@chromium.org>
+
+        Web Inspector: [Styles] Retain selector case as written in the source code
+        https://bugs.webkit.org/show_bug.cgi?id=103118
+
+        Reviewed by Antti Koivisto.
+
+        * inspector/styles/selector-list-expected.txt: Added.
+        * inspector/styles/selector-list.html: Added.
+        * inspector/styles/styles-add-new-rule-expected.txt: Rebaselined.
+
 2012-12-02  Christophe Dumez  <christophe.dumez@intel.com>
 
         Unreviewed, WebKit2 gardening.
diff --git a/LayoutTests/inspector/styles/selector-list-expected.txt b/LayoutTests/inspector/styles/selector-list-expected.txt
new file mode 100644 (file)
index 0000000..e0e06af
--- /dev/null
@@ -0,0 +1,30 @@
+Tests representation of selector lists in the protocol. Bug 103118.
+
+Text
+[expanded] 
+element.style  { ()
+
+======== Matched CSS Rules ========
+[expanded] 
+FOO bAr, #inspected, MOO>BAR, htML div, Foo~Moo, MOO  { (selector-list.html:19)
+color: green;
+
+[expanded] 
+#inspected  { (selector-list.html:10)
+
+[expanded] 
+#InSpEcTeD  { (selector-list.html:7)
+
+[expanded] 
+#inspected  { (selector-list.html:4)
+
+[expanded] 
+FOO bAr, #inspected, MOO>BAR, htML div, Foo~Moo, MOO  { (selector-list.html:19)
+/-- overloaded --/ color: green;
+
+[expanded] 
+div  { (user agent stylesheet)
+display: block;
+
+
+
diff --git a/LayoutTests/inspector/styles/selector-list.html b/LayoutTests/inspector/styles/selector-list.html
new file mode 100644 (file)
index 0000000..95fec66
--- /dev/null
@@ -0,0 +1,51 @@
+<html>
+<head>
+<style>
+#inspected{
+}
+
+#InSpEcTeD {
+}
+
+/* */#inspected/* */ {
+}
+
+/* 
+ */ FOO/*Single-line 1*/ bAr,/* Single-line 2*/#inspected/*
+    Multiline comment
+*/ ,MOO>BAR, /*1*/htML /*2
+*/div/*3*/,/**/Foo~/**C*/Moo,/**/MOO /* Comment
+ */ 
+{
+  color: green;
+}
+
+</style>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/elements-test.js"></script>
+<script>
+
+function test()
+{
+    WebInspector.showPanel("elements");
+    InspectorTest.selectNodeAndWaitForStyles("inspected", step1);
+
+    function step1()
+    {
+        InspectorTest.dumpSelectedElementStyles(true);
+        InspectorTest.completeTest();
+    }
+}
+
+</script>
+</head>
+
+<body onload="runTest()">
+<p>
+Tests representation of selector lists in the protocol. <a href="https://bugs.webkit.org/show_bug.cgi?id=103118">Bug 103118</a>.
+</p>
+
+<div id="inspected">Text</div>
+
+</body>
+</html>
index b4c899a..c48cddf 100644 (file)
@@ -13,7 +13,7 @@ foo, [$#inspected$], bar  { (inspector-stylesheet:1)
 color: maroon;
 
 [expanded] 
-div  { (user agent stylesheet)
+[$div$]  { (user agent stylesheet)
 display: block;
 
 
index 23e72f4..aa99f45 100644 (file)
@@ -1,3 +1,42 @@
+2012-12-03  Alexander Pavlov  <apavlov@chromium.org>
+
+        Web Inspector: [Styles] Retain selector case as written in the source code
+        https://bugs.webkit.org/show_bug.cgi?id=103118
+
+        Reviewed by Antti Koivisto.
+
+        This change:
+        - adds parsing of selector group components in the CSSParser;
+        - builds the SelectorList.selectors based on the source code whenever possible.
+          Strips [multiline] comments and whitespace;
+        - adds the MultilineMode to RegularExpression.
+
+        Test: inspector/styles/selector-list.html
+
+        * WebCore.exp.in: Update the exported symbol.
+        * css/CSSGrammar.y.in: Add invocations for CSSParser::markSelector[Start|End]() as required.
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::markSelectorStart): Gets invoked to mark a selector group item start offset.
+        (WebCore::CSSParser::markSelectorEnd): Ditto for the end offset.
+        * css/CSSParser.h: Add new methods and a SourceRange tracking field.
+        * css/CSSPropertySourceData.h: Add SelectorRangeList to the CSSRuleSourceData.
+        * inspector/InspectorStyleSheet.cpp:
+        (WebCore::selectorsFromSource): Builds the SelectorList based on the underlying source data.
+        Strips comments and whitespace from selectors.
+        (WebCore::InspectorStyleSheet::buildObjectForSelectorList):
+        Builds SelectorList based on the availability of the source code.
+        * inspector/front-end/StylesSidebarPane.js:
+        (WebInspector.StylePropertiesSection.prototype._markSelectorMatches):
+        Update selectors in all cases to make use of the source-based information whenever possible.
+        * platform/text/RegularExpression.cpp:
+        Add the MultilineMode parameter into the constructor/factory method and ultimately pass it into YarrPattern.
+        (WebCore::RegularExpression::Private::create): See above.
+        (WebCore::RegularExpression::Private::Private): See above.
+        (WebCore::RegularExpression::Private::compile): See above.
+        (WebCore::RegularExpression::RegularExpression): See above.
+        * platform/text/RegularExpression.h:
+        Add enum MultilineMode, modify constructor and factory method signatures accordingly.
+
 2012-12-02  Noel Gordon  <noel.gordon@gmail.com>
 
         ImageOrientation::transformFromDefault() case labels should be in numerical order
index 9395b48..8dd56ac 100644 (file)
@@ -502,7 +502,7 @@ __ZN7WebCore17JSDOMGlobalObject6s_infoE
 __ZN7WebCore17languageDidChangeEv
 __ZN7WebCore17MouseRelatedEvent7offsetXEv
 __ZN7WebCore17MouseRelatedEvent7offsetYEv
-__ZN7WebCore17RegularExpressionC1ERKN3WTF6StringENS1_19TextCaseSensitivityE
+__ZN7WebCore17RegularExpressionC1ERKN3WTF6StringENS1_19TextCaseSensitivityENS_13MultilineModeE
 __ZN7WebCore17RegularExpressionD1Ev
 __ZN7WebCore17SubresourceLoader6createEPNS_5FrameEPNS_14CachedResourceERKNS_15ResourceRequestERKNS_21ResourceLoaderOptionsE
 __ZN7WebCore17ViewportArguments19deprecatedTargetDPIE
index f08e486..03eb8e9 100644 (file)
@@ -1020,6 +1020,7 @@ maybe_space_before_declaration:
 before_selector_list:
     /* empty */ {
         parser->markRuleHeaderStart(CSSRuleSourceData::STYLE_RULE);
+        parser->markSelectorStart();
     }
   ;
 
@@ -1029,12 +1030,23 @@ at_rule_header_end:
     }
   ;
 
+at_selector_end:
+    /* empty */ {
+        parser->markSelectorEnd();
+    }
+  ;
+
 ruleset:
-    before_selector_list selector_list at_rule_header_end '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
+    before_selector_list selector_list at_selector_end at_rule_header_end '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace {
         $$ = parser->createStyleRule($2);
     }
   ;
 
+before_selector_group_item:
+    /* empty */ {
+        parser->markSelectorStart();
+    }
+
 selector_list:
     selector %prec UNIMPORTANT_TOK {
         if ($1) {
@@ -1044,10 +1056,10 @@ selector_list:
             parser->updateLastSelectorLineAndPosition();
         }
     }
-    | selector_list ',' maybe_space selector %prec UNIMPORTANT_TOK {
-        if ($1 && $4) {
+    | selector_list at_selector_end ',' maybe_space before_selector_group_item selector %prec UNIMPORTANT_TOK {
+        if ($1 && $6) {
             $$ = $1;
-            $$->append(parser->sinkFloatingSelector($4));
+            $$->append(parser->sinkFloatingSelector($6));
             parser->updateLastSelectorLineAndPosition();
         } else
             $$ = 0;
index 5275817..3abe9b5 100644 (file)
@@ -10809,6 +10809,28 @@ void CSSParser::markRuleHeaderEnd()
         setRuleHeaderEnd<UChar>(m_dataStart16.get());
 }
 
+void CSSParser::markSelectorStart()
+{
+    if (!isExtractingSourceData())
+        return;
+    ASSERT(!m_selectorRange.end);
+
+    m_selectorRange.start = tokenStartOffset();
+}
+
+void CSSParser::markSelectorEnd()
+{
+    if (!isExtractingSourceData())
+        return;
+    ASSERT(!m_selectorRange.end);
+    ASSERT(m_currentRuleDataStack->size());
+
+    m_selectorRange.end = tokenStartOffset();
+    m_currentRuleDataStack->last()->selectorRanges.append(m_selectorRange);
+    m_selectorRange.start = 0;
+    m_selectorRange.end = 0;
+}
+
 void CSSParser::markRuleBodyStart()
 {
     if (!isExtractingSourceData())
index 4205829..82cd30d 100644 (file)
@@ -353,6 +353,7 @@ public:
 
     // tokenizer methods and data
     size_t m_parsedTextPrefixLength;
+    SourceRange m_selectorRange;
     SourceRange m_propertyRange;
     OwnPtr<RuleSourceDataList> m_currentRuleDataStack;
     RefPtr<CSSRuleSourceData> m_currentRuleData;
@@ -361,6 +362,8 @@ public:
     void fixUnparsedPropertyRanges(CSSRuleSourceData*);
     void markRuleHeaderStart(CSSRuleSourceData::Type);
     void markRuleHeaderEnd();
+    void markSelectorStart();
+    void markSelectorEnd();
     void markRuleBodyStart();
     void markRuleBodyEnd();
     void markPropertyStart();
index 8982acf..e12aaae 100644 (file)
@@ -83,6 +83,7 @@ struct CSSStyleSourceData : public RefCounted<CSSStyleSourceData> {
 
 struct CSSRuleSourceData;
 typedef Vector<RefPtr<CSSRuleSourceData> > RuleSourceDataList;
+typedef Vector<SourceRange> SelectorRangeList;
 
 struct CSSRuleSourceData : public RefCounted<CSSRuleSourceData> {
     enum Type {
@@ -124,6 +125,9 @@ struct CSSRuleSourceData : public RefCounted<CSSRuleSourceData> {
     // Range of the rule body (e.g. style text for style rules) in the enclosing source.
     SourceRange ruleBodyRange;
 
+    // Only for CSSStyleRules.
+    SelectorRangeList selectorRanges;
+
     // Only for CSSStyleRules, CSSFontFaceRules, and CSSPageRules.
     RefPtr<CSSStyleSourceData> styleSourceData;
 
index eab2eb4..f67311e 100644 (file)
@@ -47,6 +47,7 @@
 #include "InspectorPageAgent.h"
 #include "InspectorValues.h"
 #include "Node.h"
+#include "RegularExpression.h"
 #include "SVGNames.h"
 #include "StyleResolver.h"
 #include "StyleRule.h"
@@ -952,20 +953,44 @@ PassRefPtr<TypeBuilder::CSS::CSSStyleSheetHeader> InspectorStyleSheet::buildObje
     return result.release();
 }
 
-PassRefPtr<TypeBuilder::CSS::SelectorList> InspectorStyleSheet::buildObjectForSelectorList(CSSStyleRule* rule)
+static PassRefPtr<TypeBuilder::Array<String> > selectorsFromSource(const CSSRuleSourceData* sourceData, const String& sheetText)
 {
-    RefPtr<TypeBuilder::Array<String> > selectors = TypeBuilder::Array<String>::create();
-    const CSSSelectorList& selectorList = rule->styleRule()->selectorList();
-    for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector))
-        selectors->addItem(selector->selectorText());
+    DEFINE_STATIC_LOCAL(RegularExpression, comment, ("/\\*[^]*?\\*/", TextCaseSensitive, MultilineEnabled));
+    RefPtr<TypeBuilder::Array<String> > result = TypeBuilder::Array<String>::create();
+    const SelectorRangeList& ranges = sourceData->selectorRanges;
+    for (size_t i = 0, size = ranges.size(); i < size; ++i) {
+        const SourceRange& range = ranges.at(i);
+        String selector = sheetText.substring(range.start, range.length());
 
-    RefPtr<TypeBuilder::CSS::SelectorList> result = TypeBuilder::CSS::SelectorList::create()
-        .setSelectors(selectors)
-        .setText(rule->selectorText());
+        // We don't want to see any comments in the selector components, only the meaningful parts.
+        replace(selector, comment, "");
+        result->addItem(selector.stripWhiteSpace());
+    }
+    return result.release();
+}
 
+PassRefPtr<TypeBuilder::CSS::SelectorList> InspectorStyleSheet::buildObjectForSelectorList(CSSStyleRule* rule)
+{
     RefPtr<CSSRuleSourceData> sourceData;
     if (ensureParsedDataReady())
         sourceData = ruleSourceDataFor(rule->style());
+    RefPtr<TypeBuilder::Array<String> > selectors;
+
+    // This intentionally does not rely on the source data to avoid catching the trailing comments (before the declaration starting '{').
+    String selectorText = rule->selectorText();
+
+    if (sourceData)
+        selectors = selectorsFromSource(sourceData.get(), m_parsedStyleSheet->text());
+    else {
+        selectors = TypeBuilder::Array<String>::create();
+        const CSSSelectorList& selectorList = rule->styleRule()->selectorList();
+        for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector))
+            selectors->addItem(selector->selectorText());
+    }
+    RefPtr<TypeBuilder::CSS::SelectorList> result = TypeBuilder::CSS::SelectorList::create()
+        .setSelectors(selectors)
+        .setText(selectorText)
+        .release();
     if (sourceData)
         result->setRange(buildSourceRangeObject(sourceData->ruleHeaderRange));
     return result.release();
index f7196a1..623e524 100644 (file)
@@ -1090,7 +1090,7 @@ WebInspector.StylePropertiesSection.prototype = {
 
         var selectors = rule.selectors;
         var matchingSelectors = rule.matchingSelectors;
-        if (selectors.length < 2 || !matchingSelectors)
+        if (!matchingSelectors)
             return;
 
         var fragment = document.createDocumentFragment();
index 2369590..71591aa 100644 (file)
@@ -36,9 +36,9 @@ namespace WebCore {
 
 class RegularExpression::Private : public RefCounted<RegularExpression::Private> {
 public:
-    static PassRefPtr<Private> create(const String& pattern, TextCaseSensitivity caseSensitivity)
+    static PassRefPtr<Private> create(const String& pattern, TextCaseSensitivity caseSensitivity, MultilineMode multilineMode)
     {
-        return adoptRef(new Private(pattern, caseSensitivity));
+        return adoptRef(new Private(pattern, caseSensitivity, multilineMode));
     }
 
     int lastMatchLength;
@@ -47,16 +47,16 @@ public:
     OwnPtr<JSC::Yarr::BytecodePattern> m_regExpByteCode;
 
 private:
-    Private(const String& pattern, TextCaseSensitivity caseSensitivity)
+    Private(const String& pattern, TextCaseSensitivity caseSensitivity, MultilineMode multilineMode)
         : lastMatchLength(-1)
-        , m_regExpByteCode(compile(pattern, caseSensitivity))
+        , m_regExpByteCode(compile(pattern, caseSensitivity, multilineMode))
         , m_constructionError(0)
     {
     }
 
-    PassOwnPtr<JSC::Yarr::BytecodePattern> compile(const String& patternString, TextCaseSensitivity caseSensitivity)
+    PassOwnPtr<JSC::Yarr::BytecodePattern> compile(const String& patternString, TextCaseSensitivity caseSensitivity, MultilineMode multilineMode)
     {
-        JSC::Yarr::YarrPattern pattern(patternString, (caseSensitivity == TextCaseInsensitive), false, &m_constructionError);
+        JSC::Yarr::YarrPattern pattern(patternString, (caseSensitivity == TextCaseInsensitive), (multilineMode == MultilineEnabled), &m_constructionError);
         if (m_constructionError) {
             LOG_ERROR("RegularExpression: YARR compile failed with '%s'", m_constructionError);
             return nullptr;
@@ -71,8 +71,8 @@ private:
     const char* m_constructionError;
 };
 
-RegularExpression::RegularExpression(const String& pattern, TextCaseSensitivity caseSensitivity)
-    : d(Private::create(pattern, caseSensitivity))
+RegularExpression::RegularExpression(const String& pattern, TextCaseSensitivity caseSensitivity, MultilineMode multilineMode)
+    : d(Private::create(pattern, caseSensitivity, multilineMode))
 {
 }
 
index 7c48faa..c628cdb 100644 (file)
 
 namespace WebCore {
 
+enum MultilineMode {
+    MultilineDisabled,
+    MultilineEnabled
+};
+
 class RegularExpression {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    RegularExpression(const String&, TextCaseSensitivity);
+    RegularExpression(const String&, TextCaseSensitivity, MultilineMode = MultilineDisabled);
     ~RegularExpression();
 
     RegularExpression(const RegularExpression&);