Skip to content

Commit bac17a6

Browse files
committed
introduce model class NotPseudoClassCondition and update the parser
1 parent 9401c3f commit bac17a6

File tree

8 files changed

+276
-125
lines changed

8 files changed

+276
-125
lines changed

pom.xml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>net.sourceforge.htmlunit</groupId>
66
<artifactId>htmlunit-cssparser</artifactId>
7-
<version>1.13.0</version>
7+
<version>1.14.0-SNAPSHOT</version>
88
<name>HtmlUnit CSS Parser</name>
99
<packaging>jar</packaging>
1010
<description>CSS parser for HtmlUnit.</description>
@@ -71,7 +71,7 @@
7171
<!-- generate parsers and lexers before compiling -->
7272
<groupId>org.codehaus.mojo</groupId>
7373
<artifactId>javacc-maven-plugin</artifactId>
74-
<version>2.6</version>
74+
<version>3.0.1</version>
7575
<executions>
7676
<execution>
7777
<id>javacc</id>
@@ -88,7 +88,6 @@
8888
</dependency>
8989
</dependencies>
9090
</plugin>
91-
<!--
9291
<plugin>
9392
<groupId>com.google.code.maven-replacer-plugin</groupId>
9493
<artifactId>replacer</artifactId>
@@ -141,7 +140,6 @@
141140
</replacements>
142141
</configuration>
143142
</plugin>
144-
-->
145143
<plugin>
146144
<groupId>org.apache.maven.plugins</groupId>
147145
<artifactId>maven-checkstyle-plugin</artifactId>

src/main/java/com/gargoylesoftware/css/parser/condition/Condition.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ enum ConditionType {
4141
PREFIX_ATTRIBUTE_CONDITION,
4242
/** PSEUDO_CLASS_CONDITION. */
4343
PSEUDO_CLASS_CONDITION,
44+
/** NOT_PSEUDO_CLASS_CONDITION. */
45+
NOT_PSEUDO_CLASS_CONDITION,
4446
/** SUBSTRING_ATTRIBUTE_CONDITION. */
4547
SUBSTRING_ATTRIBUTE_CONDITION,
4648
/** SUFFIX_ATTRIBUTE_CONDITION. */
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright (c) 2019-2021 Ronald Brill.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
package com.gargoylesoftware.css.parser.condition;
16+
17+
import java.io.Serializable;
18+
19+
import com.gargoylesoftware.css.parser.AbstractLocatable;
20+
import com.gargoylesoftware.css.parser.Locator;
21+
import com.gargoylesoftware.css.parser.selector.SelectorList;
22+
23+
/**
24+
* Not contition.
25+
*
26+
* @author Ronald Brill
27+
*/
28+
public class NotPseudoClassCondition extends AbstractLocatable implements Condition, Serializable {
29+
30+
private final SelectorList selectors_;
31+
private final boolean doubleColon_;
32+
33+
/**
34+
* Ctor.
35+
* @param selectors the selector list
36+
* @param locator the locator
37+
* @param doubleColon true if was prefixed by double colon
38+
*/
39+
public NotPseudoClassCondition(final SelectorList selectors, final Locator locator, final boolean doubleColon) {
40+
selectors_ = selectors;
41+
setLocator(locator);
42+
doubleColon_ = doubleColon;
43+
}
44+
45+
@Override
46+
public ConditionType getConditionType() {
47+
return ConditionType.NOT_PSEUDO_CLASS_CONDITION;
48+
}
49+
50+
/**
51+
* {@inheritDoc}
52+
*/
53+
@Override
54+
public String getLocalName() {
55+
return null;
56+
}
57+
58+
/**
59+
* {@inheritDoc}
60+
*/
61+
@Override
62+
public String getValue() {
63+
return selectors_.toString();
64+
}
65+
66+
/**
67+
* @return the list of selectors
68+
*/
69+
public SelectorList getSelectors() {
70+
return selectors_;
71+
}
72+
73+
@Override
74+
public String toString() {
75+
return (doubleColon_ ? "::" : ":") + "not(" + getValue() + ")";
76+
}
77+
}

src/main/java/com/gargoylesoftware/css/parser/selector/SelectorSpecificity.java

Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.io.Serializable;
1818

1919
import com.gargoylesoftware.css.parser.condition.Condition;
20+
import com.gargoylesoftware.css.parser.condition.NotPseudoClassCondition;
2021

2122
/**
2223
* Calculates a selector's specificity.
@@ -30,16 +31,16 @@ public class SelectorSpecificity implements Comparable<SelectorSpecificity>, Ser
3031
/**
3132
* The specificity for declarations made in the style attributes of an element.
3233
*/
33-
public static final SelectorSpecificity FROM_STYLE_ATTRIBUTE = new SelectorSpecificity(1, 0, 0, 0);
34+
public static final SelectorSpecificity FROM_STYLE_ATTRIBUTE = new SelectorSpecificity(true, 0, 0, 0);
3435
/**
3536
* The specificity for browser defaults.
3637
*/
37-
public static final SelectorSpecificity DEFAULT_STYLE_ATTRIBUTE = new SelectorSpecificity(0, 0, 0, 0);
38+
public static final SelectorSpecificity DEFAULT_STYLE_ATTRIBUTE = new SelectorSpecificity(false, 0, 0, 0);
3839

39-
private int fieldA_;
40-
private int fieldB_;
41-
private int fieldC_;
42-
private int fieldD_;
40+
private int fromStyle_;
41+
private int idCount_;
42+
private int classCount_;
43+
private int typeCount_;
4344

4445
/**
4546
* Ctor.
@@ -49,11 +50,11 @@ public SelectorSpecificity(final Selector selector) {
4950
readSelectorSpecificity(selector);
5051
}
5152

52-
private SelectorSpecificity(final int a, final int b, final int c, final int d) {
53-
fieldA_ = a;
54-
fieldB_ = b;
55-
fieldC_ = c;
56-
fieldD_ = d;
53+
private SelectorSpecificity(final boolean fromStyle, final int idCount, final int classCount, final int typeCount) {
54+
fromStyle_ = fromStyle ? 1 : 0;
55+
idCount_ = idCount;
56+
classCount_ = classCount;
57+
typeCount_ = typeCount;
5758
}
5859

5960
private void readSelectorSpecificity(final Selector selector) {
@@ -71,7 +72,7 @@ private void readSelectorSpecificity(final Selector selector) {
7172
case ELEMENT_NODE_SELECTOR:
7273
final ElementSelector es = (ElementSelector) selector;
7374
if (es.getLocalName() != null) {
74-
fieldD_++;
75+
typeCount_++;
7576
}
7677
if (es.getConditions() != null) {
7778
for (final Condition condition : es.getConditions()) {
@@ -83,7 +84,7 @@ private void readSelectorSpecificity(final Selector selector) {
8384
final PseudoElementSelector pes = (PseudoElementSelector) selector;
8485
final String pesName = pes.getLocalName();
8586
if (pesName != null) {
86-
fieldD_++;
87+
typeCount_++;
8788
}
8889
return;
8990
case DIRECT_ADJACENT_SELECTOR:
@@ -105,34 +106,41 @@ private void readSelectorSpecificity(final Selector selector) {
105106
private void readSelectorSpecificity(final Condition condition) {
106107
switch (condition.getConditionType()) {
107108
case ID_CONDITION:
108-
fieldB_++;
109+
idCount_++;
109110
return;
110111
case CLASS_CONDITION:
111-
fieldC_++;
112+
classCount_++;
112113
return;
113114
case ATTRIBUTE_CONDITION:
114-
fieldC_++;
115+
classCount_++;
115116
return;
116117
case SUBSTRING_ATTRIBUTE_CONDITION:
117-
fieldC_++;
118+
classCount_++;
118119
return;
119120
case SUFFIX_ATTRIBUTE_CONDITION:
120-
fieldC_++;
121+
classCount_++;
121122
return;
122123
case PREFIX_ATTRIBUTE_CONDITION:
123-
fieldC_++;
124+
classCount_++;
124125
return;
125126
case BEGIN_HYPHEN_ATTRIBUTE_CONDITION:
126-
fieldC_++;
127+
classCount_++;
127128
return;
128129
case ONE_OF_ATTRIBUTE_CONDITION:
129-
fieldC_++;
130+
classCount_++;
131+
return;
132+
case NOT_PSEUDO_CLASS_CONDITION:
133+
final NotPseudoClassCondition notPseudoCondition = (NotPseudoClassCondition) condition;
134+
final SelectorList selectorList = notPseudoCondition.getSelectors();
135+
for (final Selector selector : selectorList) {
136+
readSelectorSpecificity(selector);
137+
}
130138
return;
131139
case PSEUDO_CLASS_CONDITION:
132-
fieldC_++;
140+
classCount_++;
133141
return;
134142
case LANG_CONDITION:
135-
fieldC_++;
143+
classCount_++;
136144
return;
137145
default:
138146
throw new RuntimeException("Unhandled CSS condition type for specifity computation: '"
@@ -145,25 +153,26 @@ private void readSelectorSpecificity(final Condition condition) {
145153
*/
146154
@Override
147155
public String toString() {
148-
return fieldA_ + "," + fieldB_ + "," + fieldC_ + "," + fieldD_;
156+
// return (fromStyle_ > 0 ? "!" : "") + idCount_ + "," + classCount_ + "," + typeCount_;
157+
return fromStyle_ + "," + idCount_ + "," + classCount_ + "," + typeCount_;
149158
}
150159

151160
/**
152161
* {@inheritDoc}
153162
*/
154163
@Override
155164
public int compareTo(final SelectorSpecificity other) {
156-
if (fieldA_ != other.fieldA_) {
157-
return fieldA_ - other.fieldA_;
165+
if (fromStyle_ != other.fromStyle_) {
166+
return fromStyle_ - other.fromStyle_;
158167
}
159-
else if (fieldB_ != other.fieldB_) {
160-
return fieldB_ - other.fieldB_;
168+
else if (idCount_ != other.idCount_) {
169+
return idCount_ - other.idCount_;
161170
}
162-
else if (fieldC_ != other.fieldC_) {
163-
return fieldC_ - other.fieldC_;
171+
else if (classCount_ != other.classCount_) {
172+
return classCount_ - other.classCount_;
164173
}
165-
else if (fieldD_ != other.fieldD_) {
166-
return fieldD_ - other.fieldD_;
174+
else if (typeCount_ != other.typeCount_) {
175+
return typeCount_ - other.typeCount_;
167176
}
168177
return 0;
169178
}
@@ -172,10 +181,10 @@ else if (fieldD_ != other.fieldD_) {
172181
public int hashCode() {
173182
final int prime = 31;
174183
int result = 1;
175-
result = prime * result + fieldA_;
176-
result = prime * result + fieldB_;
177-
result = prime * result + fieldC_;
178-
result = prime * result + fieldD_;
184+
result = prime * result + fromStyle_;
185+
result = prime * result + idCount_;
186+
result = prime * result + classCount_;
187+
result = prime * result + typeCount_;
179188
return result;
180189
}
181190

@@ -191,16 +200,16 @@ public boolean equals(final Object obj) {
191200
return false;
192201
}
193202
final SelectorSpecificity other = (SelectorSpecificity) obj;
194-
if (fieldA_ != other.fieldA_) {
203+
if (fromStyle_ != other.fromStyle_) {
195204
return false;
196205
}
197-
if (fieldB_ != other.fieldB_) {
206+
if (idCount_ != other.idCount_) {
198207
return false;
199208
}
200-
if (fieldC_ != other.fieldC_) {
209+
if (classCount_ != other.classCount_) {
201210
return false;
202211
}
203-
if (fieldD_ != other.fieldD_) {
212+
if (typeCount_ != other.typeCount_) {
204213
return false;
205214
}
206215
return true;

src/main/javacc/CSS3Parser.jj

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import com.gargoylesoftware.css.parser.condition.ClassCondition;
5050
import com.gargoylesoftware.css.parser.condition.Condition;
5151
import com.gargoylesoftware.css.parser.condition.IdCondition;
5252
import com.gargoylesoftware.css.parser.condition.LangCondition;
53+
import com.gargoylesoftware.css.parser.condition.NotPseudoClassCondition;
5354
import com.gargoylesoftware.css.parser.condition.OneOfAttributeCondition;
5455
import com.gargoylesoftware.css.parser.condition.PrefixAttributeCondition;
5556
import com.gargoylesoftware.css.parser.condition.PseudoClassCondition;
@@ -1368,6 +1369,7 @@ Object pseudo(boolean pseudoElementFound) :
13681369
String function;
13691370
String arg;
13701371
boolean doubleColon = false;
1372+
SelectorList selectorList;
13711373
Locator locator;
13721374
}
13731375
{
@@ -1394,14 +1396,11 @@ Object pseudo(boolean pseudoElementFound) :
13941396
(
13951397
t = <FUNCTION_NOT> { function = unescape(t.image, false); }
13961398
( <S> )*
1397-
arg = negation_arg() {
1398-
if ("".equals(arg)) { arg = "*"; }
1399-
}
1400-
( <S> )*
1399+
selectorList = selectorList()
14011400
<RROUND>
14021401
{
1403-
if (pseudoElementFound) { throw toCSSParseException("duplicatePseudo", new String[] { function + arg + ")" }, locator); }
1404-
return new PseudoClassCondition(function + arg + ")", locator, doubleColon);
1402+
if (pseudoElementFound) { throw toCSSParseException("duplicatePseudo", new String[] { function + selectorList + ")" }, locator); }
1403+
return new NotPseudoClassCondition(selectorList, locator, doubleColon);
14051404
}
14061405
)
14071406
|
@@ -2082,28 +2081,6 @@ LexicalUnit hslColor(LexicalUnit prev) :
20822081
}
20832082
}
20842083

2085-
//
2086-
// negation_arg
2087-
// : type_selector | universal | HASH | class | attrib | pseudo
2088-
// ;
2089-
//
2090-
String negation_arg() :
2091-
{
2092-
Condition c = null;
2093-
SimpleSelector simpleSel = null;
2094-
Object o;
2095-
}
2096-
{
2097-
simpleSel = elementName() { return simpleSel.toString(); }
2098-
| c = hash(false) { return c.toString(); }
2099-
| c = _class(false) { return c.toString(); }
2100-
| c = attrib(false) { return c.toString(); }
2101-
| o = pseudo(false)
2102-
{ if (o instanceof Condition) { return o.toString(); }
2103-
return new DescendantSelector(null, (SimpleSelector) o).toString();
2104-
}
2105-
}
2106-
21072084
//
21082085
// number()
21092086
//

0 commit comments

Comments
 (0)