Commit 7305ba9e authored by Jonathan Metzman's avatar Jonathan Metzman Committed by Commit Bot

Add @supports rules generation to proto fuzzer.

Bug: 771641

Change-Id: Ia075b8ffe5b8ddeeab3549c9ed782d058a27733d
Reviewed-on: https://chromium-review.googlesource.com/746049Reviewed-by: default avatarDarren Shen <shend@chromium.org>
Reviewed-by: default avatarMax Moroz <mmoroz@chromium.org>
Commit-Queue: Jonathan Metzman <metzman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#512984}
parent ed423616
...@@ -581,11 +581,47 @@ message NestedAtRule { ...@@ -581,11 +581,47 @@ message NestedAtRule {
Page page = 3; Page page = 3;
FontFace font_face = 4; FontFace font_face = 4;
Viewport viewport = 5; Viewport viewport = 5;
SupportsRule supports_rule = 6;
} }
} }
message SupportsRule {
required SupportsCondition supports_condition = 1;
repeated AtRuleOrRulesets at_rule_or_rulesets = 2;
}
message AtRuleOrRulesets {
required AtRuleOrRuleset first = 1;
repeated AtRuleOrRuleset laters = 2;
}
message AtRuleOrRuleset {
required Ruleset ruleset = 1;
optional NestedAtRule at_rule = 2;
}
message SupportsCondition {
// Using PropertyAndValue rather than declaration means that there
// will always be a declaration. This is syntactically correct but
// means we may miss some error paths.
// TODO(metzman): Figure out what to do about generating invalid output that
// causes more coverage. Maybe doing so infrequently is the correct move.
required PropertyAndValue property_and_value = 1; // Default.
// TODO(metzman): Do functions also need to be supported?
required bool not_condition = 2;
oneof rhs {
BinarySupportsCondition and_supports_condition = 3;
BinarySupportsCondition or_supports_condition = 4;
}
}
message BinarySupportsCondition {
required SupportsCondition condition_1 = 1;
required SupportsCondition condition_2 = 2;
}
message Viewport { message Viewport {
repeated ViewportPropertyAndValue props_and_vals = 1; repeated ViewportPropertyAndValue properties_and_values = 1;
} }
message ViewportPropertyAndValue { message ViewportPropertyAndValue {
...@@ -1520,10 +1556,10 @@ message Pseudo { ...@@ -1520,10 +1556,10 @@ message Pseudo {
message Declaration { message Declaration {
// property ':' S* expr prio? | /* empty */ // property ':' S* expr prio? | /* empty */
optional NonEmptyDeclaration nonempty_declaration = 1; optional PropertyAndValue property_and_value = 1;
} }
message NonEmptyDeclaration { message PropertyAndValue {
required Property property = 1; required Property property = 1;
required Expr expr = 2; required Expr expr = 2;
enum Prio { enum Prio {
......
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
namespace css_proto_converter { namespace css_proto_converter {
const int Converter::kAtRuleDepthLimit = 5;
const int Converter::kSupportsConditionDepthLimit = 5;
const std::string Converter::kViewportPropertyLookupTable[] = { const std::string Converter::kViewportPropertyLookupTable[] = {
"", // This is just to fill the zeroth spot. It should not be used. "", // This is just to fill the zeroth spot. It should not be used.
"min-width", "max-width", "width", "min-height", "min-width", "max-width", "width", "min-height",
...@@ -1633,8 +1636,8 @@ void Converter::Visit(const ViewportValue& viewport_value) { ...@@ -1633,8 +1636,8 @@ void Converter::Visit(const ViewportValue& viewport_value) {
void Converter::Visit(const Viewport& viewport) { void Converter::Visit(const Viewport& viewport) {
string_ += " @viewport {"; string_ += " @viewport {";
for (auto& prop_and_val : viewport.props_and_vals()) for (auto& property_and_value : viewport.properties_and_values())
AppendPropertyAndValue(prop_and_val, kViewportPropertyLookupTable); AppendPropertyAndValue(property_and_value, kViewportPropertyLookupTable);
string_ += " } "; string_ += " } ";
} }
...@@ -1645,17 +1648,78 @@ void Converter::Visit(const CharsetDeclaration& charset_declaration) { ...@@ -1645,17 +1648,78 @@ void Converter::Visit(const CharsetDeclaration& charset_declaration) {
string_ += "\"; "; string_ += "\"; ";
} }
void Converter::Visit(const NestedAtRule& nested_at_rule) { void Converter::Visit(const AtRuleOrRulesets& at_rule_or_rulesets, int depth) {
Visit(at_rule_or_rulesets.first(), depth);
for (auto& later : at_rule_or_rulesets.laters())
Visit(later, depth);
}
void Converter::Visit(const AtRuleOrRuleset& at_rule_or_ruleset, int depth) {
if (at_rule_or_ruleset.has_at_rule())
Visit(at_rule_or_ruleset.at_rule(), depth);
else // Default.
Visit(at_rule_or_ruleset.ruleset());
}
void Converter::Visit(const NestedAtRule& nested_at_rule, int depth) {
if (++depth > kAtRuleDepthLimit)
return;
if (nested_at_rule.has_ruleset()) if (nested_at_rule.has_ruleset())
Visit(nested_at_rule.ruleset()); Visit(nested_at_rule.ruleset());
else if (nested_at_rule.has_media()) else if (nested_at_rule.has_media())
Visit(nested_at_rule.media()); Visit(nested_at_rule.media());
else if (nested_at_rule.has_viewport()) else if (nested_at_rule.has_viewport())
Visit(nested_at_rule.viewport()); Visit(nested_at_rule.viewport());
else if (nested_at_rule.has_supports_rule())
Visit(nested_at_rule.supports_rule(), depth);
// Else apppend nothing. // Else apppend nothing.
// TODO(metzman): Support pages and font-faces. // TODO(metzman): Support pages and font-faces.
} }
void Converter::Visit(const SupportsRule& supports_rule, int depth) {
string_ += "@supports ";
Visit(supports_rule.supports_condition(), depth);
string_ += " { ";
for (auto& at_rule_or_ruleset : supports_rule.at_rule_or_rulesets())
Visit(at_rule_or_ruleset, depth);
string_ += " } ";
}
void Converter::AppendBinarySupportsCondition(
const BinarySupportsCondition& binary_condition,
std::string binary_operator,
int depth) {
Visit(binary_condition.condition_1(), depth);
string_ += " " + binary_operator + " ";
Visit(binary_condition.condition_2(), depth);
}
void Converter::Visit(const SupportsCondition& supports_condition, int depth) {
bool under_depth_limit = ++depth <= kSupportsConditionDepthLimit;
if (supports_condition.not_condition())
string_ += " not ";
string_ += "(";
if (under_depth_limit && supports_condition.has_and_supports_condition()) {
AppendBinarySupportsCondition(supports_condition.or_supports_condition(),
"and", depth);
} else if (under_depth_limit &&
supports_condition.has_or_supports_condition()) {
AppendBinarySupportsCondition(supports_condition.or_supports_condition(),
"or", depth);
} else {
// Use the required property_and_value field if the or_supports_condition
// and and_supports_condition are unset or if we have reached the depth
// limit and don't want another nested condition.
Visit(supports_condition.property_and_value());
}
string_ += ")";
}
void Converter::Visit(const Import& import) { void Converter::Visit(const Import& import) {
string_ += "@import "; string_ += "@import ";
AppendTableValue(import.src_id(), kImportLookupTable); AppendTableValue(import.src_id(), kImportLookupTable);
...@@ -1912,20 +1976,20 @@ void Converter::Visit(const Selector& selector, bool is_first) { ...@@ -1912,20 +1976,20 @@ void Converter::Visit(const Selector& selector, bool is_first) {
} }
void Converter::Visit(const Declaration& declaration) { void Converter::Visit(const Declaration& declaration) {
if (declaration.has_nonempty_declaration()) if (declaration.has_property_and_value())
Visit(declaration.nonempty_declaration()); Visit(declaration.property_and_value());
// else empty // else empty
} }
void Converter::Visit(const NonEmptyDeclaration& nonempty_declaration) { void Converter::Visit(const PropertyAndValue& property_and_value) {
Visit(nonempty_declaration.property()); Visit(property_and_value.property());
string_ += " : "; string_ += " : ";
int value_id = 0; int value_id = 0;
if (nonempty_declaration.has_value_id()) if (property_and_value.has_value_id())
value_id = nonempty_declaration.value_id(); value_id = property_and_value.value_id();
Visit(nonempty_declaration.expr(), value_id); Visit(property_and_value.expr(), value_id);
if (nonempty_declaration.has_prio()) if (property_and_value.has_prio())
string_ += " !important"; string_ += " !important ";
} }
void Converter::Visit(const Expr& expr, int declaration_value_id) { void Converter::Visit(const Expr& expr, int declaration_value_id) {
...@@ -2015,7 +2079,7 @@ void Converter::Visit(const HexcolorThree& hexcolor_three) { ...@@ -2015,7 +2079,7 @@ void Converter::Visit(const HexcolorThree& hexcolor_three) {
} }
void Converter::Reset() { void Converter::Reset() {
string_ = ""; string_.clear();
} }
template <size_t TableSize> template <size_t TableSize>
......
...@@ -18,6 +18,9 @@ class Converter { ...@@ -18,6 +18,9 @@ class Converter {
private: private:
std::string string_; std::string string_;
static const int kAtRuleDepthLimit;
static const int kSupportsConditionDepthLimit;
static const std::string kPseudoLookupTable[]; static const std::string kPseudoLookupTable[];
static const std::string kMediaTypeLookupTable[]; static const std::string kMediaTypeLookupTable[];
static const std::string kMfNameLookupTable[]; static const std::string kMfNameLookupTable[];
...@@ -49,7 +52,7 @@ class Converter { ...@@ -49,7 +52,7 @@ class Converter {
void Visit(const FunctionToken&); void Visit(const FunctionToken&);
void Visit(const StyleSheet&); void Visit(const StyleSheet&);
void Visit(const CharsetDeclaration&); void Visit(const CharsetDeclaration&);
void Visit(const NestedAtRule&); void Visit(const NestedAtRule&, int depth = 0);
void Visit(const Import&); void Visit(const Import&);
void Visit(const Namespace&); void Visit(const Namespace&);
void Visit(const NamespacePrefix&); void Visit(const NamespacePrefix&);
...@@ -63,7 +66,7 @@ class Converter { ...@@ -63,7 +66,7 @@ class Converter {
void Visit(const Ruleset&); void Visit(const Ruleset&);
void Visit(const SelectorList&); void Visit(const SelectorList&);
void Visit(const Declaration&); void Visit(const Declaration&);
void Visit(const NonEmptyDeclaration&); void Visit(const PropertyAndValue&);
void Visit(const Expr&, int declaration_value_id = 0); void Visit(const Expr&, int declaration_value_id = 0);
void Visit(const OperatorTerm&); void Visit(const OperatorTerm&);
void Visit(const Term&); void Visit(const Term&);
...@@ -89,6 +92,15 @@ class Converter { ...@@ -89,6 +92,15 @@ class Converter {
void Visit(const PseudoPage&); void Visit(const PseudoPage&);
void Visit(const ViewportValue&); void Visit(const ViewportValue&);
void Visit(const Viewport&); void Visit(const Viewport&);
void Visit(const SupportsRule&, int depth);
void Visit(const SupportsCondition&, int depth);
void AppendBinarySupportsCondition(
const BinarySupportsCondition& binary_condition,
std::string binary_operator,
int depth);
void Visit(const AtRuleOrRulesets&, int depth);
void Visit(const AtRuleOrRuleset&, int depth);
void Reset(); void Reset();
template <class T, size_t TableSize> template <class T, size_t TableSize>
void AppendPropertyAndValue(T property_and_value, void AppendPropertyAndValue(T property_and_value,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment