feat(css/ast): Derive more traits (#4220)

This commit is contained in:
Alexander Akait 2022-04-02 08:35:05 +03:00 committed by GitHub
parent 0bac3d08f0
commit def2826029
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 325 additions and 25 deletions

View File

@ -1,3 +1,4 @@
use is_macro::Is;
use string_enum::StringEnum;
use swc_common::{ast_node, EqIgnoreSpan, Span};
@ -7,6 +8,7 @@ use crate::{
};
#[ast_node("AtRule")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct AtRule {
pub span: Span,
pub name: AtRuleName,
@ -15,6 +17,7 @@ pub struct AtRule {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum AtRuleName {
#[tag("DashedIdent")]
DashedIdent(DashedIdent),
@ -24,6 +27,7 @@ pub enum AtRuleName {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum AtRulePrelude {
#[tag("ListOfComponentValues")]
ListOfComponentValues(ListOfComponentValues),
@ -58,12 +62,14 @@ pub enum AtRulePrelude {
}
#[ast_node("ListOfComponentValues")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct ListOfComponentValues {
pub span: Span,
pub children: Vec<ComponentValue>,
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum ColorProfileName {
#[tag("DashedIdent")]
DashedIdent(DashedIdent),
@ -72,12 +78,14 @@ pub enum ColorProfileName {
}
#[ast_node("DocumentPrelude")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct DocumentPrelude {
pub span: Span,
pub matching_functions: Vec<DocumentPreludeMatchingFunction>,
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum DocumentPreludeMatchingFunction {
#[tag("Url")]
Url(Url),
@ -86,6 +94,7 @@ pub enum DocumentPreludeMatchingFunction {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum KeyframesName {
#[tag("CustomIdent")]
CustomIdent(CustomIdent),
@ -94,6 +103,7 @@ pub enum KeyframesName {
}
#[ast_node("KeyframeBlock")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct KeyframeBlock {
pub span: Span,
pub prelude: Vec<KeyframeSelector>,
@ -101,6 +111,7 @@ pub struct KeyframeBlock {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum KeyframeSelector {
#[tag("Ident")]
Ident(Ident),
@ -109,6 +120,7 @@ pub enum KeyframeSelector {
}
#[ast_node("ImportPrelude")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct ImportPrelude {
pub span: Span,
pub href: ImportPreludeHref,
@ -118,6 +130,7 @@ pub struct ImportPrelude {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum ImportPreludeHref {
#[tag("Url")]
Url(Url),
@ -126,6 +139,7 @@ pub enum ImportPreludeHref {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum ImportPreludeLayerName {
#[tag("Ident")]
Ident(Ident),
@ -134,6 +148,7 @@ pub enum ImportPreludeLayerName {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum ImportPreludeSupportsType {
#[tag("SupportsCondition")]
SupportsCondition(SupportsCondition),
@ -142,6 +157,7 @@ pub enum ImportPreludeSupportsType {
}
#[ast_node("NamespacePrelude")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct NamespacePrelude {
pub span: Span,
pub prefix: Option<Ident>,
@ -149,6 +165,7 @@ pub struct NamespacePrelude {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum NamespacePreludeUri {
#[tag("Url")]
Url(Url),
@ -157,12 +174,14 @@ pub enum NamespacePreludeUri {
}
#[ast_node("MediaQueryList")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct MediaQueryList {
pub span: Span,
pub queries: Vec<MediaQuery>,
}
#[ast_node("MediaQuery")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct MediaQuery {
pub span: Span,
pub modifier: Option<Ident>,
@ -172,6 +191,7 @@ pub struct MediaQuery {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum MediaConditionType {
#[tag("MediaCondition")]
All(MediaCondition),
@ -181,18 +201,21 @@ pub enum MediaConditionType {
}
#[ast_node("MediaCondition")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct MediaCondition {
pub span: Span,
pub conditions: Vec<MediaConditionAllType>,
}
#[ast_node("MediaConditionWithoutOr")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct MediaConditionWithoutOr {
pub span: Span,
pub conditions: Vec<MediaConditionWithoutOrType>,
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum MediaConditionAllType {
#[tag("MediaNot")]
Not(MediaNot),
@ -208,6 +231,7 @@ pub enum MediaConditionAllType {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum MediaConditionWithoutOrType {
#[tag("MediaNot")]
Not(MediaNot),
@ -220,6 +244,7 @@ pub enum MediaConditionWithoutOrType {
}
#[ast_node("MediaNot")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct MediaNot {
pub span: Span,
pub keyword: Ident,
@ -227,6 +252,7 @@ pub struct MediaNot {
}
#[ast_node("MediaAnd")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct MediaAnd {
pub span: Span,
pub keyword: Ident,
@ -234,6 +260,7 @@ pub struct MediaAnd {
}
#[ast_node("MediaOr")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct MediaOr {
pub span: Span,
pub keyword: Ident,
@ -241,6 +268,7 @@ pub struct MediaOr {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum MediaInParens {
#[tag("MediaCondition")]
MediaCondition(MediaCondition),
@ -251,6 +279,7 @@ pub enum MediaInParens {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum MediaFeature {
#[tag("MediaFeaturePlain")]
Plain(MediaFeaturePlain),
@ -266,12 +295,14 @@ pub enum MediaFeature {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum MediaFeatureName {
#[tag("Ident")]
Ident(Ident),
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum MediaFeatureValue {
#[tag("Number")]
Number(Number),
@ -287,6 +318,7 @@ pub enum MediaFeatureValue {
}
#[ast_node("MediaFeaturePlain")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct MediaFeaturePlain {
pub span: Span,
pub name: MediaFeatureName,
@ -294,6 +326,7 @@ pub struct MediaFeaturePlain {
}
#[ast_node("MediaFeatureBoolean")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct MediaFeatureBoolean {
pub span: Span,
pub name: MediaFeatureName,
@ -318,6 +351,7 @@ pub enum MediaFeatureRangeComparison {
}
#[ast_node("MediaFeatureRange")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct MediaFeatureRange {
pub span: Span,
pub left: MediaFeatureValue,
@ -326,6 +360,7 @@ pub struct MediaFeatureRange {
}
#[ast_node("MediaFeatureRangeInterval")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct MediaFeatureRangeInterval {
pub span: Span,
pub left: MediaFeatureValue,
@ -338,12 +373,14 @@ pub struct MediaFeatureRangeInterval {
}
#[ast_node("SupportsCondition")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct SupportsCondition {
pub span: Span,
pub conditions: Vec<SupportsConditionType>,
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum SupportsConditionType {
#[tag("SupportsNot")]
Not(SupportsNot),
@ -359,6 +396,7 @@ pub enum SupportsConditionType {
}
#[ast_node("SupportsNot")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct SupportsNot {
pub span: Span,
pub keyword: Ident,
@ -366,6 +404,7 @@ pub struct SupportsNot {
}
#[ast_node("SupportsAnd")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct SupportsAnd {
pub span: Span,
pub keyword: Ident,
@ -373,6 +412,7 @@ pub struct SupportsAnd {
}
#[ast_node("SupportsOr")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct SupportsOr {
pub span: Span,
pub keyword: Ident,
@ -380,6 +420,7 @@ pub struct SupportsOr {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum SupportsInParens {
#[tag("SupportsCondition")]
SupportsCondition(SupportsCondition),
@ -392,6 +433,7 @@ pub enum SupportsInParens {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum SupportsFeature {
#[tag("Declaration")]
Declaration(Declaration),
@ -400,6 +442,7 @@ pub enum SupportsFeature {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum GeneralEnclosed {
#[tag("Function")]
Function(Function),
@ -408,12 +451,14 @@ pub enum GeneralEnclosed {
}
#[ast_node("PageSelectorList")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct PageSelectorList {
pub span: Span,
pub selectors: Vec<PageSelector>,
}
#[ast_node("PageSelector")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct PageSelector {
pub span: Span,
pub page_type: Option<PageSelectorType>,
@ -421,18 +466,21 @@ pub struct PageSelector {
}
#[ast_node("PageSelectorType")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct PageSelectorType {
pub span: Span,
pub value: Ident,
}
#[ast_node("PageSelectorPseudo")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct PageSelectorPseudo {
pub span: Span,
pub value: Ident,
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum LayerPrelude {
#[tag("LayerName")]
Name(LayerName),
@ -441,12 +489,14 @@ pub enum LayerPrelude {
}
#[ast_node("LayerName")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct LayerName {
pub span: Span,
pub name: Vec<Ident>,
}
#[ast_node("LayerNameList")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct LayerNameList {
pub span: Span,
pub name_list: Vec<LayerName>,

View File

@ -1,20 +1,21 @@
use is_macro::Is;
use swc_common::{ast_node, Span};
use swc_common::{ast_node, EqIgnoreSpan, Span};
use crate::{
AlphaValue, AtRule, CalcSum, CmykComponent, Color, ComplexSelector, DashedIdent, Delimiter,
Dimension, Function, Hue, Ident, Integer, KeyframeBlock, Number, Percentage, Ratio,
SelectorList, Str, TokenAndSpan, Tokens, UnicodeRange, Url,
Dimension, Hue, Ident, Integer, KeyframeBlock, Number, Percentage, Ratio, SelectorList, Str,
TokenAndSpan, Tokens, UnicodeRange, Url,
};
#[ast_node("Stylesheet")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Stylesheet {
pub span: Span,
pub rules: Vec<Rule>,
}
#[ast_node]
#[derive(Is)]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum Rule {
#[tag("QualifiedRule")]
QualifiedRule(QualifiedRule),
@ -27,6 +28,7 @@ pub enum Rule {
}
#[ast_node("QualifiedRule")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct QualifiedRule {
pub span: Span,
pub prelude: QualifiedRulePrelude,
@ -34,6 +36,7 @@ pub struct QualifiedRule {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum QualifiedRulePrelude {
#[tag("SelectorList")]
SelectorList(SelectorList),
@ -42,6 +45,7 @@ pub enum QualifiedRulePrelude {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum StyleBlock {
#[tag("AtRule")]
AtRule(AtRule),
@ -54,6 +58,7 @@ pub enum StyleBlock {
}
#[ast_node("SimpleBlock")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct SimpleBlock {
pub span: Span,
// TODO Create a simple block with its associated token set to the current input token and with
@ -62,7 +67,17 @@ pub struct SimpleBlock {
pub value: Vec<ComponentValue>,
}
#[ast_node("Function")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Function {
/// Span starting from the `lo` of identifier and to the end of `)`.
pub span: Span,
pub name: Ident,
pub value: Vec<ComponentValue>,
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum ComponentValue {
// No grammar
#[tag("TokenAndSpan")]
@ -122,6 +137,7 @@ pub enum ComponentValue {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum DeclarationOrAtRule {
#[tag("Declaration")]
Declaration(Declaration),
@ -132,6 +148,7 @@ pub enum DeclarationOrAtRule {
}
#[ast_node("Declaration")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Declaration {
pub span: Span,
pub name: DeclarationName,
@ -141,6 +158,7 @@ pub struct Declaration {
}
#[ast_node]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub enum DeclarationName {
#[tag("Ident")]
Ident(Ident),
@ -149,6 +167,7 @@ pub enum DeclarationName {
}
#[ast_node("ImportantFlag")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct ImportantFlag {
pub span: Span,
pub value: Ident,

View File

@ -6,31 +6,35 @@ use swc_common::{ast_node, EqIgnoreSpan, Span};
use crate::{Delimiter, Ident, Str, TokenAndSpan};
#[ast_node("SelectorList")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct SelectorList {
pub span: Span,
pub children: Vec<ComplexSelector>,
}
#[ast_node("CompoundSelectorList")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct CompoundSelectorList {
pub span: Span,
pub children: Vec<CompoundSelector>,
}
#[ast_node("RelativeSelectorList")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct RelativeSelectorList {
pub span: Span,
pub children: Vec<RelativeSelector>,
}
#[ast_node("ComplexSelector")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct ComplexSelector {
pub span: Span,
pub children: Vec<ComplexSelectorChildren>,
}
#[ast_node]
#[derive(Is)]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum ComplexSelectorChildren {
#[tag("CompoundSelector")]
CompoundSelector(CompoundSelector),
@ -39,6 +43,7 @@ pub enum ComplexSelectorChildren {
}
#[ast_node("RelativeSelector")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct RelativeSelector {
pub span: Span,
pub combinator: Option<Combinator>,
@ -47,6 +52,7 @@ pub struct RelativeSelector {
/// e.g. `foo.c1.c2`
#[ast_node("CompoundSelector")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct CompoundSelector {
pub span: Span,
/// "&"
@ -56,6 +62,7 @@ pub struct CompoundSelector {
}
#[ast_node("Combinator")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Combinator {
pub span: Span,
pub value: CombinatorValue,
@ -80,11 +87,13 @@ pub enum CombinatorValue {
}
#[ast_node("NestingSelector")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct NestingSelector {
pub span: Span,
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum TypeSelector {
#[tag("TagNameSelector")]
TagName(TagNameSelector),
@ -93,24 +102,28 @@ pub enum TypeSelector {
}
#[ast_node("TagNameSelector")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct TagNameSelector {
pub span: Span,
pub name: WqName,
}
#[ast_node("UniversalSelector")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct UniversalSelector {
pub span: Span,
pub prefix: Option<NsPrefix>,
}
#[ast_node("NsPrefix")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct NsPrefix {
pub span: Span,
pub prefix: Option<Ident>,
}
#[ast_node("WqName")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct WqName {
pub span: Span,
pub prefix: Option<NsPrefix>,
@ -118,6 +131,7 @@ pub struct WqName {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum SubclassSelector {
#[tag("IdSelector")]
Id(IdSelector),
@ -136,6 +150,7 @@ pub enum SubclassSelector {
}
#[ast_node("IdSelector")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct IdSelector {
pub span: Span,
/// Does not include `#`
@ -143,6 +158,7 @@ pub struct IdSelector {
}
#[ast_node("ClassSelector")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct ClassSelector {
pub span: Span,
/// Does not include `.`
@ -150,6 +166,7 @@ pub struct ClassSelector {
}
#[ast_node("AttributeSelector")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct AttributeSelector {
pub span: Span,
pub name: WqName,
@ -180,12 +197,14 @@ pub enum AttributeSelectorMatcherValue {
}
#[ast_node("AttributeSelectorMatcher")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct AttributeSelectorMatcher {
pub span: Span,
pub value: AttributeSelectorMatcherValue,
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum AttributeSelectorValue {
#[tag("String")]
Str(Str),
@ -195,12 +214,14 @@ pub enum AttributeSelectorValue {
}
#[ast_node("AttributeSelectorModifier")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct AttributeSelectorModifier {
pub span: Span,
pub value: Ident,
}
#[ast_node("PseudoClassSelector")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct PseudoClassSelector {
pub span: Span,
pub name: Ident,
@ -208,6 +229,7 @@ pub struct PseudoClassSelector {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum PseudoClassSelectorChildren {
#[tag("TokenAndSpan")]
PreservedToken(TokenAndSpan),
@ -238,6 +260,7 @@ pub enum PseudoClassSelectorChildren {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum AnPlusB {
#[tag("Ident")]
Ident(Ident),
@ -246,6 +269,7 @@ pub enum AnPlusB {
}
#[ast_node("AnPlusBNotation")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct AnPlusBNotation {
pub span: Span,
pub a: Option<i32>,
@ -255,6 +279,7 @@ pub struct AnPlusBNotation {
}
#[ast_node("PseudoElementSelector")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct PseudoElementSelector {
pub span: Span,
pub name: Ident,
@ -262,13 +287,12 @@ pub struct PseudoElementSelector {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum PseudoElementSelectorChildren {
#[tag("TokenAndSpan")]
PreservedToken(TokenAndSpan),
#[tag("Ident")]
Ident(Ident),
#[tag("CompoundSelector")]
CompoundSelector(CompoundSelector),
}

View File

@ -1,21 +1,27 @@
use std::{
hash::{Hash, Hasher},
mem,
};
use serde::{Deserialize, Serialize};
use swc_atoms::JsWord;
use swc_common::{ast_node, Span};
use swc_common::{ast_node, EqIgnoreSpan, Span};
#[ast_node("Tokens")]
#[derive(Default)]
#[derive(Default, Eq, Hash, EqIgnoreSpan)]
pub struct Tokens {
pub span: Span,
pub tokens: Vec<TokenAndSpan>,
}
#[ast_node("PreservedToken")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct TokenAndSpan {
pub span: Span,
pub token: Token,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, EqIgnoreSpan)]
pub enum NumberType {
#[serde(rename = "integer")]
Integer,
@ -23,7 +29,7 @@ pub enum NumberType {
Number,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, EqIgnoreSpan)]
pub enum Token {
Ident {
value: JsWord,
@ -138,3 +144,112 @@ pub enum Token {
/// `}`
RBrace,
}
#[allow(clippy::derive_hash_xor_eq)]
#[allow(clippy::transmute_float_to_int)]
impl Hash for Token {
fn hash<H: Hasher>(&self, state: &mut H) {
fn integer_decode(val: f64) -> (u64, i16, i8) {
let bits: u64 = unsafe { mem::transmute(val) };
let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
let mantissa = if exponent == 0 {
(bits & 0xfffffffffffff) << 1
} else {
(bits & 0xfffffffffffff) | 0x10000000000000
};
exponent -= 1023 + 52;
(mantissa, exponent, sign)
}
match self {
Token::Ident { value, raw }
| Token::Function { value, raw }
| Token::AtKeyword { value, raw }
| Token::String { value, raw }
| Token::BadString { value, raw } => {
value.hash(state);
raw.hash(state);
}
Token::Hash { value, raw, is_id } => {
value.hash(state);
raw.hash(state);
is_id.hash(state);
}
Token::Url {
name,
raw_name,
before,
after,
value,
raw_value,
} => {
name.hash(state);
raw_name.hash(state);
before.hash(state);
after.hash(state);
value.hash(state);
raw_value.hash(state);
}
Token::BadUrl {
name,
raw_name,
value,
raw_value,
} => {
name.hash(state);
raw_name.hash(state);
value.hash(state);
raw_value.hash(state);
}
Token::Delim { value } => {
value.hash(state);
}
Token::Number {
value,
raw,
type_flag,
} => {
integer_decode(*value).hash(state);
raw.hash(state);
type_flag.hash(state);
}
Token::Percentage { value, raw } => {
integer_decode(*value).hash(state);
raw.hash(state);
}
Token::Dimension {
value,
raw_value,
unit,
raw_unit,
type_flag,
} => {
integer_decode(*value).hash(state);
raw_value.hash(state);
unit.hash(state);
raw_unit.hash(state);
type_flag.hash(state);
}
Token::WhiteSpace { value } => {
value.hash(state);
}
Token::CDO
| Token::CDC
| Token::Colon
| Token::Semi
| Token::Comma
| Token::LBracket
| Token::RBracket
| Token::LParen
| Token::RParen
| Token::LBrace
| Token::RBrace => {
self.hash(state);
}
}
}
}
impl Eq for Token {}

View File

@ -1,50 +1,86 @@
use std::{
hash::{Hash, Hasher},
mem,
};
use is_macro::Is;
use string_enum::StringEnum;
use swc_atoms::JsWord;
use swc_common::{ast_node, EqIgnoreSpan, Span};
use crate::ComponentValue;
use crate::Function;
#[ast_node("Ident")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[derive(Eq, Hash)]
pub struct Ident {
pub span: Span,
pub value: JsWord,
pub raw: JsWord,
}
impl EqIgnoreSpan for Ident {
fn eq_ignore_span(&self, other: &Self) -> bool {
self.value == other.value
}
}
#[ast_node("CustomIdent")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[derive(Eq, Hash)]
pub struct CustomIdent {
pub span: Span,
pub value: JsWord,
pub raw: JsWord,
}
impl EqIgnoreSpan for CustomIdent {
fn eq_ignore_span(&self, other: &Self) -> bool {
self.value == other.value
}
}
#[ast_node("DashedIdent")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[derive(Eq, Hash)]
pub struct DashedIdent {
pub span: Span,
pub value: JsWord,
pub raw: JsWord,
}
impl EqIgnoreSpan for DashedIdent {
fn eq_ignore_span(&self, other: &Self) -> bool {
self.value == other.value
}
}
#[ast_node("CustomPropertyName")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[derive(Eq, Hash)]
pub struct CustomPropertyName {
pub span: Span,
pub value: JsWord,
pub raw: JsWord,
}
impl EqIgnoreSpan for CustomPropertyName {
fn eq_ignore_span(&self, other: &Self) -> bool {
self.value == other.value
}
}
/// Quoted string.
#[ast_node("String")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[derive(Eq, Hash)]
pub struct Str {
pub span: Span,
pub value: JsWord,
pub raw: JsWord,
}
impl EqIgnoreSpan for Str {
fn eq_ignore_span(&self, other: &Self) -> bool {
self.value == other.value
}
}
#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan)]
pub enum DelimiterValue {
/// `,`
@ -62,17 +98,10 @@ pub struct Delimiter {
pub value: DelimiterValue,
}
#[ast_node("Function")]
pub struct Function {
/// Span starting from the `lo` of identifier and to the end of `)`.
pub span: Span,
pub name: Ident,
pub value: Vec<ComponentValue>,
}
// TODO small AST improve for `CurrentColorOrSystemColor` and
// `NamedColorOrTransparent`
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum Color {
#[tag("AbsoluteColorBase")]
AbsoluteColorBase(AbsoluteColorBase),
@ -84,6 +113,7 @@ pub enum Color {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum AbsoluteColorBase {
#[tag("HexColor")]
HexColor(HexColor),
@ -105,6 +135,7 @@ pub struct HexColor {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum AlphaValue {
#[tag("Number")]
Number(Number),
@ -113,6 +144,7 @@ pub enum AlphaValue {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum Hue {
#[tag("Number")]
Number(Number),
@ -121,6 +153,7 @@ pub enum Hue {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum CmykComponent {
#[tag("Number")]
Number(Number),
@ -131,6 +164,7 @@ pub enum CmykComponent {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum Dimension {
#[tag("Length")]
Length(Length),
@ -155,6 +189,7 @@ pub enum Dimension {
}
#[ast_node("Length")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Length {
pub span: Span,
pub value: Number,
@ -162,6 +197,7 @@ pub struct Length {
}
#[ast_node("Angle")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Angle {
pub span: Span,
pub value: Number,
@ -169,6 +205,7 @@ pub struct Angle {
}
#[ast_node("Time")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Time {
pub span: Span,
pub value: Number,
@ -176,6 +213,7 @@ pub struct Time {
}
#[ast_node("Frequency")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Frequency {
pub span: Span,
pub value: Number,
@ -183,6 +221,7 @@ pub struct Frequency {
}
#[ast_node("Resolution")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Resolution {
pub span: Span,
pub value: Number,
@ -190,6 +229,7 @@ pub struct Resolution {
}
#[ast_node("Flex")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Flex {
pub span: Span,
pub value: Number,
@ -197,6 +237,7 @@ pub struct Flex {
}
#[ast_node("UnknownDimension")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct UnknownDimension {
pub span: Span,
pub value: Number,
@ -204,18 +245,26 @@ pub struct UnknownDimension {
}
#[ast_node("Percentage")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Percentage {
pub span: Span,
pub value: Number,
}
#[ast_node("Integer")]
#[derive(Eq, Hash)]
pub struct Integer {
pub span: Span,
pub value: i64,
pub raw: JsWord,
}
impl EqIgnoreSpan for Integer {
fn eq_ignore_span(&self, other: &Self) -> bool {
self.value == other.value
}
}
#[ast_node("Number")]
pub struct Number {
pub span: Span,
@ -223,7 +272,39 @@ pub struct Number {
pub raw: JsWord,
}
impl Eq for Number {}
#[allow(clippy::derive_hash_xor_eq)]
#[allow(clippy::transmute_float_to_int)]
impl Hash for Number {
fn hash<H: Hasher>(&self, state: &mut H) {
fn integer_decode(val: f64) -> (u64, i16, i8) {
let bits: u64 = unsafe { mem::transmute(val) };
let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
let mantissa = if exponent == 0 {
(bits & 0xfffffffffffff) << 1
} else {
(bits & 0xfffffffffffff) | 0x10000000000000
};
exponent -= 1023 + 52;
(mantissa, exponent, sign)
}
self.span.hash(state);
integer_decode(self.value).hash(state);
}
}
impl EqIgnoreSpan for Number {
fn eq_ignore_span(&self, other: &Self) -> bool {
self.value == other.value
}
}
#[ast_node("Ratio")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Ratio {
pub span: Span,
pub left: Number,
@ -243,6 +324,7 @@ pub enum BinOp {
}
#[ast_node("Url")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Url {
pub span: Span,
pub name: Ident,
@ -251,6 +333,7 @@ pub struct Url {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum UrlValue {
#[tag("Str")]
Str(Str),
@ -259,6 +342,7 @@ pub enum UrlValue {
}
#[ast_node("UrlValueRaw")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct UrlValueRaw {
pub span: Span,
pub before: JsWord,
@ -268,6 +352,7 @@ pub struct UrlValueRaw {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum UrlModifier {
#[tag("Ident")]
Ident(Ident),
@ -276,6 +361,7 @@ pub enum UrlModifier {
}
#[ast_node("UnicodeRange")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct UnicodeRange {
pub span: Span,
pub prefix: char,
@ -284,12 +370,14 @@ pub struct UnicodeRange {
}
#[ast_node("CalcSum")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct CalcSum {
pub span: Span,
pub expressions: Vec<CalcProductOrOperator>,
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum CalcProductOrOperator {
#[tag("CalcProduct")]
Product(CalcProduct),
@ -298,12 +386,14 @@ pub enum CalcProductOrOperator {
}
#[ast_node("CalcProduct")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct CalcProduct {
pub span: Span,
pub expressions: Vec<CalcValueOrOperator>,
}
#[ast_node("CalcOperator")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct CalcOperator {
pub span: Span,
pub value: CalcOperatorType,
@ -322,6 +412,7 @@ pub enum CalcOperatorType {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum CalcValueOrOperator {
#[tag("CalcValue")]
Value(CalcValue),
@ -330,6 +421,7 @@ pub enum CalcValueOrOperator {
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
pub enum CalcValue {
#[tag("Number")]
Number(Number),