From 60af5b8e272314db55e2c210a7dfd781f74a9436 Mon Sep 17 00:00:00 2001 From: Tyler Brinks Date: Sat, 20 Jan 2024 22:46:27 -0700 Subject: [PATCH] Int parsing modified; code cleanup --- license.txt | 2 +- src/ExCSS.Tests/ExCSS.Tests.csproj | 2 +- src/ExCSS.Tests/Sheet.cs | 6 +- src/ExCSS/ExCSS.csproj | 2 +- src/ExCSS/Extensions/CharExtensions.cs | 23 +- src/ExCSS/Extensions/PortableExtensions.cs | 2 - .../Factories/AttributeSelectorFactory.cs | 8 +- src/ExCSS/Factories/PropertyFactory.cs | 8 +- src/ExCSS/MediaFeatures/MediaFeature.cs | 2 +- src/ExCSS/Model/Converters.cs | 12 +- src/ExCSS/Model/ParserExtensions.cs | 6 +- src/ExCSS/Model/Priority.cs | 33 +-- src/ExCSS/Model/StyleDeclaration.cs | 6 +- src/ExCSS/Model/StylesheetNode.cs | 8 +- src/ExCSS/Model/Symbols.cs | 10 +- src/ExCSS/Parser/Lexer.cs | 10 +- src/ExCSS/Parser/LexerBase.cs | 21 -- src/ExCSS/Parser/SelectorConstructor.cs | 244 +++++++++--------- src/ExCSS/Parser/StylesheetComposer.cs | 6 +- src/ExCSS/Parser/StylesheetParser.cs | 4 +- src/ExCSS/Tokens/NumberToken.cs | 21 +- .../OrderedOptionsConverter.cs | 2 +- .../ValueConverters/PeriodicValueConverter.cs | 8 +- .../StartsWithValueConverter.cs | 2 +- .../UnorderedOptionsConverter.cs | 2 +- src/ExCSS/Values/Angle.cs | 61 ++--- src/ExCSS/Values/Length.cs | 114 ++++---- 27 files changed, 300 insertions(+), 325 deletions(-) diff --git a/license.txt b/license.txt index d216c3c3..5ee26cb7 100644 --- a/license.txt +++ b/license.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) [year] [fullname] +Copyright (c) 2024 Tyler Brinks Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/ExCSS.Tests/ExCSS.Tests.csproj b/src/ExCSS.Tests/ExCSS.Tests.csproj index 0f8f6ede..b6affc60 100644 --- a/src/ExCSS.Tests/ExCSS.Tests.csproj +++ b/src/ExCSS.Tests/ExCSS.Tests.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 ExCSS.Tests ExCSS.Tests true diff --git a/src/ExCSS.Tests/Sheet.cs b/src/ExCSS.Tests/Sheet.cs index 26ff79ac..04e9945c 100644 --- a/src/ExCSS.Tests/Sheet.cs +++ b/src/ExCSS.Tests/Sheet.cs @@ -1,5 +1,4 @@ using System; -using System.Threading; namespace ExCSS.Tests { @@ -1261,5 +1260,10 @@ public void ShouldBeAbleToPreserveDuplicateProperties() Assert.Equal("some-invalid-color", props[1].Value); } + [Fact] + public void Parse_ZIndex_Out_Of_Range() + { + var sheet = ParseStyleSheet(".style{ z-index: 99999999999999999;}"); + } } } diff --git a/src/ExCSS/ExCSS.csproj b/src/ExCSS/ExCSS.csproj index 36f181cb..4c996cc0 100644 --- a/src/ExCSS/ExCSS.csproj +++ b/src/ExCSS/ExCSS.csproj @@ -2,7 +2,7 @@ 9.0 - net7.0;net6.0;netcoreapp3.1;net48;netstandard2.1;netstandard2.0 + net8.0;net7.0;net6.0;netcoreapp3.1;net48;netstandard2.1;netstandard2.0 ExCSS Anateus.ExCSS ExCSS .NET Stylesheet Parser diff --git a/src/ExCSS/Extensions/CharExtensions.cs b/src/ExCSS/Extensions/CharExtensions.cs index 6c628989..79fdfad3 100644 --- a/src/ExCSS/Extensions/CharExtensions.cs +++ b/src/ExCSS/Extensions/CharExtensions.cs @@ -39,12 +39,12 @@ public static bool IsNormalPathCharacter(this char c) public static bool IsUppercaseAscii(this char c) { - return c >= Symbols.CapitalA && c <= Symbols.CapitalZ; + return c is >= Symbols.CapitalA and <= Symbols.CapitalZ; } public static bool IsLowercaseAscii(this char c) { - return c >= Symbols.LowerA && c <= Symbols.LowerZ; + return c is >= Symbols.LowerA and <= Symbols.LowerZ; } public static bool IsAlphanumericAscii(this char c) @@ -54,8 +54,8 @@ public static bool IsAlphanumericAscii(this char c) public static bool IsHex(this char c) { - return c.IsDigit() || c >= Symbols.CapitalA && c <= Symbols.CapitalF || - c >= Symbols.LowerA && c <= Symbols.LowerF; + return c.IsDigit() || c is >= Symbols.CapitalA and <= Symbols.CapitalF || + c is >= Symbols.LowerA and <= Symbols.LowerF; } public static bool IsNonAscii(this char c) @@ -65,9 +65,9 @@ public static bool IsNonAscii(this char c) public static bool IsNonPrintable(this char c) { - return c >= Symbols.Null && c <= Symbols.Backspace || - c >= Symbols.ShiftOut && c <= Symbols.UnitSeparator || - c >= Symbols.Delete && c < Symbols.NonBreakingSpace; + return c is /*>= Symbols.Null and*/ <= Symbols.Backspace + or >= Symbols.ShiftOut and <= Symbols.UnitSeparator + or >= Symbols.Delete and < Symbols.NonBreakingSpace; } public static bool IsLetter(this char c) @@ -87,18 +87,17 @@ public static bool IsNameStart(this char c) public static bool IsLineBreak(this char c) { - return c == Symbols.LineFeed || c == Symbols.CarriageReturn; + return c is Symbols.LineFeed or Symbols.CarriageReturn; } public static bool IsSpaceCharacter(this char c) { - return c == Symbols.Space || c == Symbols.Tab || c == Symbols.LineFeed || - c == Symbols.CarriageReturn || c == Symbols.FormFeed; + return c is Symbols.Space or Symbols.Tab or Symbols.LineFeed or Symbols.CarriageReturn or Symbols.FormFeed; } public static bool IsDigit(this char c) { - return c >= Symbols.Zero && c <= Symbols.Nine; + return c is >= Symbols.Zero and <= Symbols.Nine; } // HTML forbids the use of Universal Character Set / Unicode code points @@ -110,7 +109,7 @@ public static bool IsDigit(this char c) public static bool IsInvalid(this int c) { return c == 0 || c > Symbols.MaximumCodepoint || - c > Symbols.UTF16SurrogateMin && c < Symbols.UTF16SurrogateMax; + c is > Symbols.UTF16SurrogateMin and < Symbols.UTF16SurrogateMax; } public static bool IsOneOf(this char c, char a, char b) diff --git a/src/ExCSS/Extensions/PortableExtensions.cs b/src/ExCSS/Extensions/PortableExtensions.cs index d1bf830c..c90f1698 100644 --- a/src/ExCSS/Extensions/PortableExtensions.cs +++ b/src/ExCSS/Extensions/PortableExtensions.cs @@ -1,8 +1,6 @@ using System; using System.Linq; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; #if !NET40 && !SL50 diff --git a/src/ExCSS/Factories/AttributeSelectorFactory.cs b/src/ExCSS/Factories/AttributeSelectorFactory.cs index b4c56424..21a9eb03 100644 --- a/src/ExCSS/Factories/AttributeSelectorFactory.cs +++ b/src/ExCSS/Factories/AttributeSelectorFactory.cs @@ -30,8 +30,8 @@ public IAttrSelector Create(string combinator, string match, string value, strin if (!string.IsNullOrEmpty(prefix)) { - name = FormFront(prefix, match); - _ = FormMatch(prefix, match); + name = AttributeSelectorFactory.FormFront(prefix, match); + _ = AttributeSelectorFactory.FormMatch(prefix, match); } return _types.TryGetValue(combinator, out var type) @@ -39,12 +39,12 @@ public IAttrSelector Create(string combinator, string match, string value, strin : new AttrAvailableSelector(name, value); } - private string FormFront(string prefix, string match) + private static string FormFront(string prefix, string match) { return string.Concat(prefix, Combinators.Pipe, match); } - private string FormMatch(string prefix, string match) + private static string FormMatch(string prefix, string match) { return prefix.Is(Keywords.Asterisk) ? match : string.Concat(prefix, PseudoClassNames.Separator, match); } diff --git a/src/ExCSS/Factories/PropertyFactory.cs b/src/ExCSS/Factories/PropertyFactory.cs index cab27437..fa42dd04 100644 --- a/src/ExCSS/Factories/PropertyFactory.cs +++ b/src/ExCSS/Factories/PropertyFactory.cs @@ -398,14 +398,14 @@ public bool IsAnimatable(string name) { return _longhands.ContainsKey(name) ? _animatables.Contains(name) - : GetLonghands(name).Any(longhand => _animatables.Contains(name)); + : GetLonghands(name).Any(_ => _animatables.Contains(name)); } public string[] GetLonghands(string name) { - return _mappings.ContainsKey(name) - ? _mappings[name] - : new string[0]; + return _mappings.TryGetValue(name, out var mapping) + ? mapping + : Array.Empty(); } public IEnumerable GetShorthands(string name) diff --git a/src/ExCSS/MediaFeatures/MediaFeature.cs b/src/ExCSS/MediaFeatures/MediaFeature.cs index 8fec320e..e8302769 100644 --- a/src/ExCSS/MediaFeatures/MediaFeature.cs +++ b/src/ExCSS/MediaFeatures/MediaFeature.cs @@ -23,7 +23,7 @@ internal MediaFeature(string name) public string Value => HasValue ? _tokenValue.Text : string.Empty; - public bool HasValue => _tokenValue != null && _tokenValue.Count > 0; + public bool HasValue => _tokenValue is {Count: > 0}; public override void ToCss(TextWriter writer, IStyleFormatter formatter) { diff --git a/src/ExCSS/Model/Converters.cs b/src/ExCSS/Model/Converters.cs index d4d42e82..4e231794 100644 --- a/src/ExCSS/Model/Converters.cs +++ b/src/ExCSS/Model/Converters.cs @@ -312,8 +312,8 @@ public static readonly IValueConverter public static readonly IValueConverter OptionalNumberConverter = NumberConverter.OrNone(); - public static readonly IValueConverter LengthOrNormalConverter = - LengthConverter.Or(Keywords.Normal, new Length(1f, Length.Unit.Em)); + //public static readonly IValueConverter LengthOrNormalConverter = + // LengthConverter.Or(Keywords.Normal, new Length(1f, Length.Unit.Em)); public static readonly IValueConverter OptionalLengthConverter = LengthConverter.Or(Keywords.Normal); public static readonly IValueConverter AutoLengthConverter = LengthConverter.OrAuto(); @@ -460,10 +460,10 @@ public static IValueConverter Toggle(string on, string off) return Assign(on, true).Or(off, false); } - public static IValueConverter WithFallback(T fallbackValue) where T : struct, IFormattable - { - return new StructValueConverter(_ => fallbackValue); - } + //public static IValueConverter WithFallback(T fallbackValue) where T : struct, IFormattable + //{ + // return new StructValueConverter(_ => fallbackValue); + //} #endregion diff --git a/src/ExCSS/Model/ParserExtensions.cs b/src/ExCSS/Model/ParserExtensions.cs index 260616a2..64dae91a 100644 --- a/src/ExCSS/Model/ParserExtensions.cs +++ b/src/ExCSS/Model/ParserExtensions.cs @@ -44,14 +44,14 @@ private static IConditionFunction CreateOrCondition(IEnumerable creator) + return FunctionTypes.TryGetValue(functionName, out _) ? TokenType.Url : TokenType.Function; } public static Func, IConditionFunction> GetCreator(this string conjunction) { - GroupCreators.TryGetValue(conjunction, out Func, IConditionFunction> creator); + GroupCreators.TryGetValue(conjunction, out var creator); return creator; } @@ -101,7 +101,7 @@ public static DocumentFunction ToDocumentFunction(this Token token) case TokenType.Url: { var functionName = ((UrlToken)token).FunctionName; - FunctionTypes.TryGetValue(functionName, out Func creator); + FunctionTypes.TryGetValue(functionName, out var creator); return creator(token.Data); } case TokenType.Function when token.Data.Isi(FunctionNames.Regexp): diff --git a/src/ExCSS/Model/Priority.cs b/src/ExCSS/Model/Priority.cs index 5bbac77a..b637c292 100644 --- a/src/ExCSS/Model/Priority.cs +++ b/src/ExCSS/Model/Priority.cs @@ -6,10 +6,6 @@ namespace ExCSS [StructLayout(LayoutKind.Explicit, Pack = 1, CharSet = CharSet.Unicode)] public struct Priority : IEquatable, IComparable { - [FieldOffset(0)] private readonly byte _tags; - [FieldOffset(1)] private readonly byte _classes; - [FieldOffset(2)] private readonly byte _ids; - [FieldOffset(3)] private readonly byte _inlines; [FieldOffset(0)] private readonly uint _priority; public static readonly Priority Zero = new (0u); @@ -20,23 +16,30 @@ public struct Priority : IEquatable, IComparable public Priority(uint priority) { - _inlines = _ids = _classes = _tags = 0; + Inlines = Ids = Classes = Tags = 0; _priority = priority; } public Priority(byte inlines, byte ids, byte classes, byte tags) { _priority = 0; - _inlines = inlines; - _ids = ids; - _classes = classes; - _tags = tags; + Inlines = inlines; + Ids = ids; + Classes = classes; + Tags = tags; } - public byte Ids => _ids; - public byte Tags => _tags; - public byte Classes => _classes; - public byte Inlines => _inlines; + [field: FieldOffset(2)] + public byte Ids { get; } + + [field: FieldOffset(0)] + public byte Tags { get; } + + [field: FieldOffset(1)] + public byte Classes { get; } + + [field: FieldOffset(3)] + public byte Inlines { get; } public static Priority operator +(Priority a, Priority b) { @@ -79,7 +82,7 @@ public bool Equals(Priority other) public override bool Equals(object obj) { - return obj is Priority && Equals((Priority) obj); + return obj is Priority priority && Equals(priority); } public override int GetHashCode() @@ -94,7 +97,7 @@ public int CompareTo(Priority other) public override string ToString() { - return $"({_inlines}, {_ids}, {_classes}, {_tags})"; + return $"({Inlines}, {Ids}, {Classes}, {Tags})"; } } } \ No newline at end of file diff --git a/src/ExCSS/Model/StyleDeclaration.cs b/src/ExCSS/Model/StyleDeclaration.cs index a99637db..5a4be073 100644 --- a/src/ExCSS/Model/StyleDeclaration.cs +++ b/src/ExCSS/Model/StyleDeclaration.cs @@ -120,7 +120,7 @@ private void RemovePropertyByName(string propertyName) public string GetPropertyPriority(string propertyName) { var property = GetProperty(propertyName); - if (property != null && property.IsImportant) return Keywords.Important; + if (property is {IsImportant: true}) return Keywords.Important; if (!IsStrictMode || !PropertyFactory.Instance.IsShorthand(propertyName)) return string.Empty; var longhands = PropertyFactory.Instance.GetLonghands(propertyName); @@ -225,12 +225,12 @@ internal void SetProperty(Property property) internal void SetDeclarations(IEnumerable declarations) { - ChangeDeclarations(declarations, m => false, (o, n) => !o.IsImportant || n.IsImportant); + ChangeDeclarations(declarations, _ => false, (o, n) => !o.IsImportant || n.IsImportant); } internal void UpdateDeclarations(IEnumerable declarations) { - ChangeDeclarations(declarations, m => !m.CanBeInherited, (o, n) => o.IsInherited); + ChangeDeclarations(declarations, m => !m.CanBeInherited, (o, _) => o.IsInherited); } private void ChangeDeclarations(IEnumerable declarations, Predicate defaultSkip, diff --git a/src/ExCSS/Model/StylesheetNode.cs b/src/ExCSS/Model/StylesheetNode.cs index aa2f8e42..2b5180a2 100644 --- a/src/ExCSS/Model/StylesheetNode.cs +++ b/src/ExCSS/Model/StylesheetNode.cs @@ -6,13 +6,7 @@ namespace ExCSS { public abstract class StylesheetNode : IStylesheetNode { - private readonly List _children; - - protected StylesheetNode() - { - _children = new List(); - StylesheetText = null; - } + private readonly List _children = new(); protected void ReplaceAll(IStylesheetNode node) { diff --git a/src/ExCSS/Model/Symbols.cs b/src/ExCSS/Model/Symbols.cs index e6161447..20d1898e 100644 --- a/src/ExCSS/Model/Symbols.cs +++ b/src/ExCSS/Model/Symbols.cs @@ -6,13 +6,13 @@ namespace ExCSS internal static class Symbols { - public static readonly string[] NewLines = { "\r\n", "\r", "\n" }; + //public static readonly string[] NewLines = { "\r\n", "\r", "\n" }; public const char StartOfHeading = (char)0x01; // Non-printable SOH public const char Backspace = (char)0x08; // Non-printable BS public const char UnitSeparator = (char)0x1F; // Non-printable US public const char ShiftOut = (char)0x0E; // Non-printable SO - public const char ShiftIn = (char)0x0F; // Non-printable SI + //public const char ShiftIn = (char)0x0F; // Non-printable SI public const char Zero = (char)0x30; // 0 public const char Seven = (char)0x37; // 7 @@ -31,7 +31,7 @@ internal static class Symbols public const char Tilde = (char) 0x7e; // ~ public const char Pipe = (char) 0x7c; // | public const char Null = (char) 0x0; - public const char Ampersand = (char) 0x26; // & + //public const char Ampersand = (char) 0x26; // & public const char Num = (char) 0x23; // # public const char Dollar = (char) 0x24; // $ public const char Semicolon = (char) 0x3b; // ; @@ -55,7 +55,7 @@ internal static class Symbols public const char FormFeed = (char) 0x0c; // form feed public const char Space = (char) 0x20; // space public const char Solidus = (char) 0x2f; // solidus / - public const char NoBreakSpace = (char) 0xa0; // no breaking space + //public const char NoBreakSpace = (char) 0xa0; // no breaking space public const char ReverseSolidus = (char) 0x5c; // reverse solidus \ public const char Colon = (char) 0x3a; // : public const char ExclamationMark = (char) 0x21; // ! @@ -73,7 +73,7 @@ internal static class Symbols public const char NonBreakingSpace = (char)0xA0; // 160 start of defined extended set public const char UTF16SurrogateMin = (char)0xD800; // 55296 public const char UTF16SurrogateMax = (char)0xDFFF; // 57343 - public static Dictionary Punycode = new Dictionary + public static Dictionary Punycode = new() { {'。', '.'}, {'.', '.'}, diff --git a/src/ExCSS/Parser/Lexer.cs b/src/ExCSS/Parser/Lexer.cs index bb724f51..d73a917d 100644 --- a/src/ExCSS/Parser/Lexer.cs +++ b/src/ExCSS/Parser/Lexer.cs @@ -710,8 +710,14 @@ private Token UrlDoubleQuote(string functionName) return UrlBad(functionName); } - if (Symbols.EndOfFile == current) return NewUrl(functionName, FlushBuffer()); - if (current == Symbols.DoubleQuote) return UrlEnd(functionName); + switch (current) + { + case Symbols.EndOfFile: + return NewUrl(functionName, FlushBuffer()); + case Symbols.DoubleQuote: + return UrlEnd(functionName); + } + if (current != Symbols.ReverseSolidus) { StringBuffer.Append(current); diff --git a/src/ExCSS/Parser/LexerBase.cs b/src/ExCSS/Parser/LexerBase.cs index 1b0e6f87..b734aa68 100644 --- a/src/ExCSS/Parser/LexerBase.cs +++ b/src/ExCSS/Parser/LexerBase.cs @@ -42,27 +42,6 @@ public TextPosition GetCurrentPosition() return new(Line, Column, Position); } - //protected bool ContinuesWithInsensitive(string val) - //{ - // var content = PeekString(val.Length); - // return (content.Length == val.Length) && content.Isi(val); - //} - - //protected bool ContinuesWithSensitive(string val) - //{ - // var content = PeekString(val.Length); - // return (content.Length == val.Length) && content.Isi(val); - //} - - //protected string PeekString(int length) - //{ - // var mark = Source.Index; - // Source.Index--; - // var content = Source.ReadCharacters(length); - // Source.Index = mark; - // return content; - //} - protected char SkipSpaces() { var c = GetNext(); diff --git a/src/ExCSS/Parser/SelectorConstructor.cs b/src/ExCSS/Parser/SelectorConstructor.cs index 4ade41c5..0a43a848 100644 --- a/src/ExCSS/Parser/SelectorConstructor.cs +++ b/src/ExCSS/Parser/SelectorConstructor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace ExCSS { @@ -49,9 +50,9 @@ private enum State : byte {PseudoClassNames.NthColumn, ctx => new ChildFunctionState(ctx, false)}, {PseudoClassNames.NthLastColumn, ctx => new ChildFunctionState(ctx, false)}, {PseudoClassNames.Not, ctx => new NotFunctionState(ctx)}, - {PseudoClassNames.Dir, ctx => new DirFunctionState()}, - {PseudoClassNames.Lang, ctx => new LangFunctionState()}, - {PseudoClassNames.Contains, ctx => new ContainsFunctionState()}, + {PseudoClassNames.Dir, _ => new DirFunctionState()}, + {PseudoClassNames.Lang, _ => new LangFunctionState()}, + {PseudoClassNames.Contains, _ => new ContainsFunctionState()}, {PseudoClassNames.Has, ctx => new HasFunctionState(ctx)}, {PseudoClassNames.Matches, ctx => new MatchesFunctionState(ctx)}, {PseudoClassNames.HostContext, ctx => new HostContextFunctionState(ctx)} @@ -337,7 +338,7 @@ private void InsertOr() { if (_temp == null) return; - if (_group == null) _group = new ListSelector(); + _group ??= new ListSelector(); if (_complex != null) { @@ -366,7 +367,7 @@ private void Insert(ISelector selector) } else { - if (_complex == null) _complex = new ComplexSelector(); + _complex ??= new ComplexSelector(); var combinator = GetCombinator(); _complex.AppendSelector(_temp, combinator); @@ -457,18 +458,17 @@ private ISelector GetPseudoFunction(FunctionToken arguments) { if (!PseudoClassFunctions.TryGetValue(arguments.Data, out var creator)) return null; - using (var function = creator(this)) + using var function = creator(this); + _ready = false; + if (arguments.Any(token => function.Finished(token))) { - _ready = false; - foreach (var token in arguments) - if (function.Finished(token)) - { - var sel = function.Produce(); - if (IsNested && function is NotFunctionState) - sel = null; - _ready = true; - return sel; - } + var sel = function.Produce(); + if (IsNested && function is NotFunctionState) + { + sel = null; + } + _ready = true; + return sel; } return null; @@ -506,13 +506,14 @@ public NotFunctionState(SelectorConstructor parent) protected override bool OnToken(Token token) { - if (token.Type != TokenType.RoundBracketClose || _selector._state != State.Data) + if (token.Type == TokenType.RoundBracketClose && _selector._state == State.Data) { - _selector.Apply(token); - return false; + return true; } - return true; + _selector.Apply(token); + return false; + } public override ISelector Produce() @@ -546,26 +547,27 @@ public HasFunctionState(SelectorConstructor parent) protected override bool OnToken(Token token) { - if (token.Type != TokenType.RoundBracketClose || _nested._state != State.Data) + if (token.Type == TokenType.RoundBracketClose && _nested._state == State.Data) { - _nested.Apply(token); - return false; + return true; } + _nested.Apply(token); + return false; - return true; } public override ISelector Produce() { var valid = _nested.IsValid; var sel = _nested.GetResult(); - if (valid) + + if (!valid) { - var code = PseudoClassNames.Has.StylesheetFunction(sel.Text); - return PseudoClassSelector.Create( /*el => el.ChildNodes.QuerySelector(sel) != null,*/ code); + return null; } - return null; + var code = PseudoClassNames.Has.StylesheetFunction(sel.Text); + return PseudoClassSelector.Create( /*el => el.ChildNodes.QuerySelector(sel) != null,*/ code); } public override void Dispose() @@ -586,26 +588,28 @@ public MatchesFunctionState(SelectorConstructor parent) protected override bool OnToken(Token token) { - if (token.Type != TokenType.RoundBracketClose || _selector._state != State.Data) + if (token.Type == TokenType.RoundBracketClose && _selector._state == State.Data) { - _selector.Apply(token); - return false; + return true; } - return true; + _selector.Apply(token); + return false; + } public override ISelector Produce() { var valid = _selector.IsValid; var sel = _selector.GetResult(); - if (valid) + if (!valid) { - var code = PseudoClassNames.Matches.StylesheetFunction(sel.Text); - return PseudoClassSelector.Create( /*el => sel.Match(el),*/ code); + return null; } - return null; + var code = PseudoClassNames.Matches.StylesheetFunction(sel.Text); + return PseudoClassSelector.Create( /*el => sel.Match(el),*/ code); + } public override void Dispose() @@ -617,22 +621,23 @@ public override void Dispose() private sealed class DirFunctionState : FunctionState { - private bool _valid; + private bool _valid = true; private string _value; - public DirFunctionState() - { - _valid = true; - _value = null; - } - protected override bool OnToken(Token token) { if (token.Type == TokenType.Ident) + { _value = token.Data; + } else if (token.Type == TokenType.RoundBracketClose) + { return true; - else if (token.Type != TokenType.Whitespace) _valid = false; + } + else if (token.Type != TokenType.Whitespace) + { + _valid = false; + } return false; } @@ -647,69 +652,71 @@ public override ISelector Produce() private sealed class LangFunctionState : FunctionState { - private bool valid; - private string value; - - public LangFunctionState() - { - valid = true; - value = null; - } + private bool valid = true; + private string value ; protected override bool OnToken(Token token) { if (token.Type == TokenType.Ident) + { value = token.Data; + } else if (token.Type == TokenType.RoundBracketClose) + { return true; - else if (token.Type != TokenType.Whitespace) valid = false; + } + else if (token.Type != TokenType.Whitespace) + { + valid = false; + } return false; } public override ISelector Produce() { - if (valid && value != null) + if (!valid || value == null) { - var code = PseudoClassNames.Lang.StylesheetFunction(value); - return PseudoClassSelector.Create(code); + return null; } + var code = PseudoClassNames.Lang.StylesheetFunction(value); + return PseudoClassSelector.Create(code); - return null; } } private sealed class ContainsFunctionState : FunctionState { - private bool _valid; + private bool _valid = true; private string _value; - public ContainsFunctionState() - { - _valid = true; - _value = null; - } - protected override bool OnToken(Token token) { - if (token.Type == TokenType.Ident || token.Type == TokenType.String) + if (token.Type is TokenType.Ident or TokenType.String) + { _value = token.Data; + } else if (token.Type == TokenType.RoundBracketClose) + { return true; - else if (token.Type != TokenType.Whitespace) _valid = false; + } + else if (token.Type != TokenType.Whitespace) + { + _valid = false; + } return false; } public override ISelector Produce() { - if (_valid && _value != null) + if (!_valid || _value == null) { - var code = PseudoClassNames.Contains.StylesheetFunction(_value); - return PseudoClassSelector.Create(code); + return null; } + var code = PseudoClassNames.Contains.StylesheetFunction(_value); + return PseudoClassSelector.Create(code); - return null; } } @@ -724,26 +731,27 @@ public HostContextFunctionState(SelectorConstructor parent) protected override bool OnToken(Token token) { - if (token.Type != TokenType.RoundBracketClose || _selector._state != State.Data) + if (token.Type == TokenType.RoundBracketClose && _selector._state == State.Data) { - _selector.Apply(token); - return false; + return true; } + _selector.Apply(token); + return false; - return true; } public override ISelector Produce() { var valid = _selector.IsValid; var sel = _selector.GetResult(); - if (valid) + if (!valid) { - var code = PseudoClassNames.HostContext.StylesheetFunction(sel.Text); - return PseudoClassSelector.Create(code); + return null; } - return null; + var code = PseudoClassNames.HostContext.StylesheetFunction(sel.Text); + return PseudoClassSelector.Create(code); + } public override void Dispose() @@ -779,46 +787,44 @@ public override ISelector Produce() var invalid = !_valid || _nested != null && !_nested.IsValid; var sel = _nested?.ToPool() ?? AllSelector.Create(); if (invalid) + { return null; + } return new T().With(_step, _offset, sel); } protected override bool OnToken(Token token) { - switch (_state) + return _state switch { - case ParseState.Initial: - return OnInitial(token); - case ParseState.AfterInitialSign: - return OnAfterInitialSign(token); - case ParseState.Offset: - return OnOffset(token); - case ParseState.BeforeOf: - return OnBeforeOf(token); - default: - return OnAfter(token); - } + ParseState.Initial => OnInitial(token), + ParseState.AfterInitialSign => OnAfterInitialSign(token), + ParseState.Offset => OnOffset(token), + ParseState.BeforeOf => OnBeforeOf(token), + _ => OnAfter(token) + }; } private bool OnAfterInitialSign(Token token) { - if (token.Type == TokenType.Number) return OnOffset(token); - if (token.Type == TokenType.Dimension) - { - var dim = (UnitToken) token; - _valid = _valid && dim.Unit.Isi("n") && int.TryParse(token.Data, out _step); - _step *= _sign; - _sign = 1; - _state = ParseState.Offset; - return false; - } - - if (token.Type == TokenType.Ident && token.Data.Isi("n")) + switch (token.Type) { - _step = _sign; - _sign = 1; - _state = ParseState.Offset; - return false; + case TokenType.Number: + return OnOffset(token); + case TokenType.Dimension: + { + var dim = (UnitToken) token; + _valid = _valid && dim.Unit.Isi("n") && int.TryParse(token.Data, out _step); + _step *= _sign; + _sign = 1; + _state = ParseState.Offset; + return false; + } + case TokenType.Ident when token.Data.Isi("n"): + _step = _sign; + _sign = 1; + _state = ParseState.Offset; + return false; } if (_state == ParseState.Initial && token.Type == TokenType.Ident && token.Data.Isi("-n")) @@ -834,13 +840,13 @@ private bool OnAfterInitialSign(Token token) private bool OnAfter(Token token) { - if (token.Type != TokenType.RoundBracketClose || _nested._state != State.Data) + if (token.Type == TokenType.RoundBracketClose && _nested._state == State.Data) { - _nested.Apply(token); - return false; + return true; } + _nested.Apply(token); + return false; - return true; } private bool OnBeforeOf(Token token) @@ -861,16 +867,18 @@ private bool OnBeforeOf(Token token) private bool OnOffset(Token token) { - if (token.Type == TokenType.Whitespace) return false; - if (token.Type == TokenType.Number) + switch (token.Type) { - _valid = _valid && ((NumberToken) token).IsInteger && int.TryParse(token.Data, out _offset); - _offset *= _sign; - _state = ParseState.BeforeOf; - return false; + case TokenType.Whitespace: + return false; + case TokenType.Number: + _valid = _valid && ((NumberToken) token).IsInteger && int.TryParse(token.Data, out _offset); + _offset *= _sign; + _state = ParseState.BeforeOf; + return false; + default: + return OnBeforeOf(token); } - - return OnBeforeOf(token); } private bool OnInitial(Token token) diff --git a/src/ExCSS/Parser/StylesheetComposer.cs b/src/ExCSS/Parser/StylesheetComposer.cs index 1bef80e5..c2df58f0 100644 --- a/src/ExCSS/Parser/StylesheetComposer.cs +++ b/src/ExCSS/Parser/StylesheetComposer.cs @@ -562,7 +562,7 @@ public TextPosition FillDeclarations(StyleDeclaration style) var sourceProperty = CreateDeclarationWith(PropertyFactory.Instance.Create, ref token); var resolvedProperties = new[] {sourceProperty}; - if (sourceProperty != null && sourceProperty.HasValue) + if (sourceProperty is {HasValue: true}) { // For shorthand properties we need to first find out what alternate set of properties they will // end up resolving into so that we can compare them with their previously parsed counterparts (if any) @@ -993,8 +993,10 @@ private TextPosition FillDeclarations(DeclarationRule rule, Func ParseAsync(Stylesheet sheet, TextSource source) var tokenizer = new Lexer(source); var start = tokenizer.GetCurrentPosition(); var builder = new StylesheetComposer(tokenizer, this); - var tasks = new List(); + //var tasks = new List(); var end = builder.CreateRules(sheet); var range = new TextRange(start, end); sheet.StylesheetText = new StylesheetText(range, source); @@ -131,7 +131,7 @@ internal async Task ParseAsync(Stylesheet sheet, TextSource source) if (rule.Type != RuleType.Import) break; } - await TaskEx.WhenAll(tasks).ConfigureAwait(false); + //await TaskEx.WhenAll(tasks).ConfigureAwait(false); return sheet; } diff --git a/src/ExCSS/Tokens/NumberToken.cs b/src/ExCSS/Tokens/NumberToken.cs index 274f0902..7950f695 100644 --- a/src/ExCSS/Tokens/NumberToken.cs +++ b/src/ExCSS/Tokens/NumberToken.cs @@ -1,4 +1,5 @@ using System.Globalization; +using System.Linq; namespace ExCSS { @@ -13,7 +14,25 @@ public NumberToken(string number, TextPosition position) public bool IsInteger => Data.IndexOfAny(FloatIndicators) == -1; - public int IntegerValue => int.Parse(Data, CultureInfo.InvariantCulture); + public int IntegerValue + { + get + { + var parsed = int.TryParse(Data, out var result); + + if (parsed) + { + return result; + } + + if (Data.All(char.IsDigit)) + { + return int.MaxValue; + } + + throw new ParseException($"Unrecognized integer value '{Data}.'"); + } + } public float Value => float.Parse(Data, CultureInfo.InvariantCulture); } diff --git a/src/ExCSS/ValueConverters/OrderedOptionsConverter.cs b/src/ExCSS/ValueConverters/OrderedOptionsConverter.cs index a82181e1..34824fcd 100644 --- a/src/ExCSS/ValueConverters/OrderedOptionsConverter.cs +++ b/src/ExCSS/ValueConverters/OrderedOptionsConverter.cs @@ -63,7 +63,7 @@ public OptionsValue(IPropertyValue[] options, IEnumerable tokens) IEnumerator IEnumerable.GetEnumerator() { - foreach (var option in _options) yield return option; + return ((IEnumerable) _options).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() diff --git a/src/ExCSS/ValueConverters/PeriodicValueConverter.cs b/src/ExCSS/ValueConverters/PeriodicValueConverter.cs index 31a7fc3a..3825d29a 100644 --- a/src/ExCSS/ValueConverters/PeriodicValueConverter.cs +++ b/src/ExCSS/ValueConverters/PeriodicValueConverter.cs @@ -11,7 +11,7 @@ internal sealed class PeriodicValueConverter : IValueConverter public PeriodicValueConverter(IValueConverter converter, string[] labels) { - Debug.Assert(labels.Length == 0 || labels.Length == 4 || labels.Length == 2); + Debug.Assert(labels.Length is 0 or 4 or 2); _converter = converter; _labels = labels; @@ -53,11 +53,11 @@ private sealed class PeriodicValue : IPropertyValue public PeriodicValue(IPropertyValue[] options, IEnumerable tokens, string[] labels) { - Debug.Assert(labels.Length == 0 || labels.Length == 2 || labels.Length == 4); + Debug.Assert(labels.Length is 0 or 2 or 4); _values = new IPropertyValue[labels.Length == 0 ? 4 : labels.Length]; - if (_values.Length == 0 || _values.Length == 4) + if (_values.Length is 0 or 4) { //Top, right, bottom, left _values[0] = options[0]; @@ -79,7 +79,7 @@ private string[] Values { get { - if (_values.Length == 0 || _values.Length == 4) + if (_values.Length is 0 or 4) { var top = _values[0].CssText; var right = _values[1].CssText; diff --git a/src/ExCSS/ValueConverters/StartsWithValueConverter.cs b/src/ExCSS/ValueConverters/StartsWithValueConverter.cs index 6c452a91..6d5ef9e9 100644 --- a/src/ExCSS/ValueConverters/StartsWithValueConverter.cs +++ b/src/ExCSS/ValueConverters/StartsWithValueConverter.cs @@ -35,7 +35,7 @@ private IPropertyValue CreateFrom(IPropertyValue value, IEnumerable token private List Transform(IEnumerable values) { - var enumerator = values.GetEnumerator(); + using var enumerator = values.GetEnumerator(); while (enumerator.MoveNext() && enumerator.Current.Type == TokenType.Whitespace) { diff --git a/src/ExCSS/ValueConverters/UnorderedOptionsConverter.cs b/src/ExCSS/ValueConverters/UnorderedOptionsConverter.cs index ecd743e9..d72c9039 100644 --- a/src/ExCSS/ValueConverters/UnorderedOptionsConverter.cs +++ b/src/ExCSS/ValueConverters/UnorderedOptionsConverter.cs @@ -78,7 +78,7 @@ public TokenValue ExtractFor(string name) { var extracted = option.ExtractFor(name); - if (extracted != null && extracted.Count > 0) + if (extracted is {Count: > 0}) { if (tokens.Count > 0) tokens.Add(Token.Whitespace); diff --git a/src/ExCSS/Values/Angle.cs b/src/ExCSS/Values/Angle.cs index c67e0ed5..03d2b26f 100644 --- a/src/ExCSS/Values/Angle.cs +++ b/src/ExCSS/Values/Angle.cs @@ -51,7 +51,7 @@ public string UnitString public static bool operator >=(Angle a, Angle b) { var result = a.CompareTo(b); - return result == 0 || result == 1; + return result is 0 or 1; } /// @@ -68,7 +68,7 @@ public string UnitString public static bool operator <=(Angle a, Angle b) { var result = a.CompareTo(b); - return result == 0 || result == -1; + return result is 0 or -1; } /// @@ -105,55 +105,36 @@ public static bool TryParse(string s, out Angle result) public static Unit GetUnit(string s) { - switch (s) + return s switch { - case "deg": - return Unit.Deg; - case "grad": - return Unit.Grad; - case "turn": - return Unit.Turn; - case "rad": - return Unit.Rad; - default: - return Unit.None; - } + "deg" => Unit.Deg, + "grad" => Unit.Grad, + "turn" => Unit.Turn, + "rad" => Unit.Rad, + _ => Unit.None + }; } public float ToRadian() { - switch (Type) + return Type switch { - case Unit.Deg: - return (float) (Math.PI / 180.0 * Value); - - case Unit.Grad: - return (float) (Math.PI / 200.0 * Value); - - case Unit.Turn: - return (float) (2.0 * Math.PI * Value); - - default: - return Value; - } + Unit.Deg => (float) (Math.PI / 180.0 * Value), + Unit.Grad => (float) (Math.PI / 200.0 * Value), + Unit.Turn => (float) (2.0 * Math.PI * Value), + _ => Value + }; } public float ToTurns() { - switch (Type) + return Type switch { - case Unit.Deg: - return (float) (Value / 360.0); - - case Unit.Grad: - return (float) (Value / 400.0); - - case Unit.Rad: - return (float) (Value / (2.0 * Math.PI)); - - default: - return Value; - } + Unit.Deg => (float) (Value / 360.0), + Unit.Grad => (float) (Value / 400.0), + Unit.Rad => (float) (Value / (2.0 * Math.PI)), + _ => Value + }; } public bool Equals(Angle other) diff --git a/src/ExCSS/Values/Length.cs b/src/ExCSS/Values/Length.cs index 24dcba59..f92b0ffe 100644 --- a/src/ExCSS/Values/Length.cs +++ b/src/ExCSS/Values/Length.cs @@ -188,85 +188,67 @@ public static bool TryParse(string s, out Length result) public static Unit GetUnit(string s) { - switch (s) + return s switch { - case "ch": - return Unit.Ch; - case "cm": - return Unit.Cm; - case "em": - return Unit.Em; - case "ex": - return Unit.Ex; - case "in": - return Unit.In; - case "mm": - return Unit.Mm; - case "pc": - return Unit.Pc; - case "pt": - return Unit.Pt; - case "px": - return Unit.Px; - case "rem": - return Unit.Rem; - case "vh": - return Unit.Vh; - case "vmax": - return Unit.Vmax; - case "vmin": - return Unit.Vmin; - case "vw": - return Unit.Vw; - case "%": - return Unit.Percent; - default: - return Unit.None; - } + "ch" => Unit.Ch, + "cm" => Unit.Cm, + "em" => Unit.Em, + "ex" => Unit.Ex, + "in" => Unit.In, + "mm" => Unit.Mm, + "pc" => Unit.Pc, + "pt" => Unit.Pt, + "px" => Unit.Px, + "rem" => Unit.Rem, + "vh" => Unit.Vh, + "vmax" => Unit.Vmax, + "vmin" => Unit.Vmin, + "vw" => Unit.Vw, + "%" => Unit.Percent, + _ => Unit.None + }; } public float ToPixel() { - switch (Type) + return Type switch { - case Unit.In: // 1 in = 2.54 cm - return Value * 96f; - case Unit.Mm: // 1 mm = 0.1 cm - return Value * 5f * 96f / 127f; - case Unit.Pc: // 1 pc = 12 pt - return Value * 12f * 96f / 72f; - case Unit.Pt: // 1 pt = 1/72 in - return Value * 96f / 72f; - case Unit.Cm: // 1 cm = 50/127 in - return Value * 50f * 96f / 127f; - case Unit.Px: // 1 px = 1/96 in - return Value; - default: - throw new InvalidOperationException("A relative unit cannot be converted."); - } + Unit.In => // 1 in = 2.54 cm + Value * 96f, + Unit.Mm => // 1 mm = 0.1 cm + Value * 5f * 96f / 127f, + Unit.Pc => // 1 pc = 12 pt + Value * 12f * 96f / 72f, + Unit.Pt => // 1 pt = 1/72 in + Value * 96f / 72f, + Unit.Cm => // 1 cm = 50/127 in + Value * 50f * 96f / 127f, + Unit.Px => // 1 px = 1/96 in + Value, + _ => throw new InvalidOperationException("A relative unit cannot be converted.") + }; } public float To(Unit unit) { var value = ToPixel(); - switch (unit) + return unit switch { - case Unit.In: // 1 in = 2.54 cm - return value / 96f; - case Unit.Mm: // 1 mm = 0.1 cm - return value * 127f / (5f * 96f); - case Unit.Pc: // 1 pc = 12 pt - return value * 72f / (12f * 96f); - case Unit.Pt: // 1 pt = 1/72 in - return value * 72f / 96f; - case Unit.Cm: // 1 cm = 50/127 in - return value * 127f / (50f * 96f); - case Unit.Px: // 1 px = 1/96 in - return value; - default: - throw new InvalidOperationException("An absolute unit cannot be converted to a relative one."); - } + Unit.In => // 1 in = 2.54 cm + value / 96f, + Unit.Mm => // 1 mm = 0.1 cm + value * 127f / (5f * 96f), + Unit.Pc => // 1 pc = 12 pt + value * 72f / (12f * 96f), + Unit.Pt => // 1 pt = 1/72 in + value * 72f / 96f, + Unit.Cm => // 1 cm = 50/127 in + value * 127f / (50f * 96f), + Unit.Px => // 1 px = 1/96 in + value, + _ => throw new InvalidOperationException("An absolute unit cannot be converted to a relative one.") + }; } public bool Equals(Length other)