diff --git a/.editorconfig b/.editorconfig index d9a0ca8..bc8cb12 100644 --- a/.editorconfig +++ b/.editorconfig @@ -55,6 +55,8 @@ csharp_style_inlined_variable_declaration = true:suggestion csharp_style_throw_expression = false:none csharp_style_conditional_delegate_call = true:suggestion +csharp_style_namespace_declarations = file_scoped:warning + # utf8 strings only clarify if it really is a string. in the case of binary data, it only obfuscates things. csharp_style_prefer_utf8_string_literals = false:none diff --git a/src/MethodCheck.Core/BinaryProcessor.cs b/src/MethodCheck.Core/BinaryProcessor.cs index d683a03..3097d13 100644 --- a/src/MethodCheck.Core/BinaryProcessor.cs +++ b/src/MethodCheck.Core/BinaryProcessor.cs @@ -2,138 +2,137 @@ using System; using System.Collections.Generic; -namespace MethodCheck.Core +namespace MethodCheck.Core; + +public static class BinaryProcessor { - public static class BinaryProcessor + public static byte[]? Parse(ReadOnlySpan text) { - public static byte[]? Parse(ReadOnlySpan text) + var index = 0; + var buffer = new List(); + var halfByte = false; + var readingComment = false; + byte tmp = 0; + + while (index < text.Length) { - var index = 0; - var buffer = new List(); - var halfByte = false; - var readingComment = false; - byte tmp = 0; + var c = text[index++]; + byte x; - while (index < text.Length) + if (c == '\r' || c == '\n') { - var c = text[index++]; - byte x; + readingComment = false; + continue; + } - if (c == '\r' || c == '\n') - { - readingComment = false; - continue; - } + if (char.IsWhiteSpace(c) || readingComment) + { + continue; + } - if (char.IsWhiteSpace(c) || readingComment) - { - continue; - } + if ((uint)(c - '0') <= 9) + { + x = unchecked((byte)(c - '0')); + } + else + { + c |= '\x20'; - if ((uint)(c - '0') <= 9) + if ((uint)(c - 'a') <= 5) { - x = unchecked((byte)(c - '0')); + x = unchecked((byte)(c - 'a' + 10)); } - else + else if (c == '/' && index < text.Length && text[index] == '/') { - c |= '\x20'; - - if ((uint)(c - 'a') <= 5) - { - x = unchecked((byte)(c - 'a' + 10)); - } - else if (c == '/' && index < text.Length && text[index] == '/') - { - readingComment = true; - index++; - continue; - } - else - { - return null; - } - } - - if (halfByte) - { - buffer.Add(unchecked((byte)(tmp | x))); - halfByte = false; + readingComment = true; + index++; + continue; } else { - tmp = unchecked((byte)(x << 4)); - halfByte = true; + return null; } } if (halfByte) { - buffer.Add(tmp); + buffer.Add(unchecked((byte)(tmp | x))); + halfByte = false; + } + else + { + tmp = unchecked((byte)(x << 4)); + halfByte = true; } + } - return buffer.ToArray(); + if (halfByte) + { + buffer.Add(tmp); } - public static string Format(ReadOnlySpan blob) + return buffer.ToArray(); + } + + public static string Format(ReadOnlySpan blob) + { + if (blob.Length == 0) { - if (blob.Length == 0) - { - return string.Empty; - } + return string.Empty; + } - // 2 characters per byte + - // one separator character per byte after the first + - // one additional separator character every 4 bytes after the first. - // - // After every 16 bytes, the separator will be a newline, otherwise it will be spaces. - var length = 2 + (((blob.Length - 1) * 13) >> 2); + // 2 characters per byte + + // one separator character per byte after the first + + // one additional separator character every 4 bytes after the first. + // + // After every 16 bytes, the separator will be a newline, otherwise it will be spaces. + var length = 2 + (((blob.Length - 1) * 13) >> 2); - if (Environment.NewLine.Length != 2) - { - // We calculated length based on Environment.NewLine being 2 characters. - // We need to adjust if it wasn't for some reason. - length += (Environment.NewLine.Length - 2) * ((blob.Length - 1) >> 4); - } + if (Environment.NewLine.Length != 2) + { + // We calculated length based on Environment.NewLine being 2 characters. + // We need to adjust if it wasn't for some reason. + length += (Environment.NewLine.Length - 2) * ((blob.Length - 1) >> 4); + } - return string.Create( - length, - blob, - static (target, blob) => - { - var write = 0; - var nl = Environment.NewLine.AsSpan(); + return string.Create( + length, + blob, + static (target, blob) => + { + var write = 0; + var nl = Environment.NewLine.AsSpan(); - WriteByte(target.Slice(write), blob[0]); - write += 2; + WriteByte(target.Slice(write), blob[0]); + write += 2; - for (var i = 1; i < blob.Length; i++) + for (var i = 1; i < blob.Length; i++) + { + if ((i & 0xF) == 0) { - if ((i & 0xF) == 0) - { - nl.CopyTo(target.Slice(write)); - write += nl.Length; - } - else + nl.CopyTo(target.Slice(write)); + write += nl.Length; + } + else + { + if ((i & 0x3) == 0) { - if ((i & 0x3) == 0) - { - target[write++] = ' '; - } - target[write++] = ' '; } - WriteByte(target.Slice(write), blob[i]); - write += 2; + target[write++] = ' '; } - }); - static void WriteByte(Span target, byte b) - { - const string Alphabet = "0123456789ABCDEF"; - target[0] = Alphabet[b >> 4]; - target[1] = Alphabet[b & 0xF]; - } + WriteByte(target.Slice(write), blob[i]); + write += 2; + } + }); + + static void WriteByte(Span target, byte b) + { + const string Alphabet = "0123456789ABCDEF"; + target[0] = Alphabet[b >> 4]; + target[1] = Alphabet[b & 0xF]; } } } diff --git a/src/MethodCheck.Core/Data/ExceptionHandler.cs b/src/MethodCheck.Core/Data/ExceptionHandler.cs index 5903843..fff84f1 100644 --- a/src/MethodCheck.Core/Data/ExceptionHandler.cs +++ b/src/MethodCheck.Core/Data/ExceptionHandler.cs @@ -1,17 +1,16 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. using System.Reflection; -namespace MethodCheck.Core.Data +namespace MethodCheck.Core.Data; + +public sealed class ExceptionHandler( + ExceptionHandlingClauseOptions type, + ILRange tryRange, + ILRange handlerRange, + int filterOrType) { - public sealed class ExceptionHandler( - ExceptionHandlingClauseOptions type, - ILRange tryRange, - ILRange handlerRange, - int filterOrType) - { - public ExceptionHandlingClauseOptions Type { get; } = type; - public ILRange TryRange { get; } = tryRange; - public ILRange HandlerRange { get; } = handlerRange; - public int FilterOrType { get; } = filterOrType; - } + public ExceptionHandlingClauseOptions Type { get; } = type; + public ILRange TryRange { get; } = tryRange; + public ILRange HandlerRange { get; } = handlerRange; + public int FilterOrType { get; } = filterOrType; } diff --git a/src/MethodCheck.Core/Data/Instruction.cs b/src/MethodCheck.Core/Data/Instruction.cs index 1409f8f..a85389c 100644 --- a/src/MethodCheck.Core/Data/Instruction.cs +++ b/src/MethodCheck.Core/Data/Instruction.cs @@ -1,41 +1,40 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. using System.Reflection.Emit; -namespace MethodCheck.Core.Data +namespace MethodCheck.Core.Data; + +public sealed class Instruction { - public sealed class Instruction + public const int MaxMnemonicLength = 14; + + public Instruction(ILRange range, OpCode opcode, object? argument) { - public const int MaxMnemonicLength = 14; + Kind = InstructionKind.OpCode; + Range = range; + OpCode = opcode; + Argument = argument; + } - public Instruction(ILRange range, OpCode opcode, object? argument) - { - Kind = InstructionKind.OpCode; - Range = range; - OpCode = opcode; - Argument = argument; - } + public Instruction(ILRange range) + { + Kind = InstructionKind.Invalid; + Range = range; + } + + public InstructionKind Kind { get; } + public ILRange Range { get; } + public OpCode OpCode { get; } + public object? Argument { get; } - public Instruction(ILRange range) + public override string ToString() + { + if (Argument == null) { - Kind = InstructionKind.Invalid; - Range = range; + return Range.Offset + ": " + OpCode.Name; } - - public InstructionKind Kind { get; } - public ILRange Range { get; } - public OpCode OpCode { get; } - public object? Argument { get; } - - public override string ToString() + else { - if (Argument == null) - { - return Range.Offset + ": " + OpCode.Name; - } - else - { - return Range.Offset + ": " + OpCode.Name + " " + Argument; - } + return Range.Offset + ": " + OpCode.Name + " " + Argument; } } } diff --git a/src/MethodCheck.Core/Data/InstructionKind.cs b/src/MethodCheck.Core/Data/InstructionKind.cs index c20c856..6152856 100644 --- a/src/MethodCheck.Core/Data/InstructionKind.cs +++ b/src/MethodCheck.Core/Data/InstructionKind.cs @@ -1,9 +1,8 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. -namespace MethodCheck.Core.Data +namespace MethodCheck.Core.Data; + +public enum InstructionKind { - public enum InstructionKind - { - Invalid, - OpCode, - } + Invalid, + OpCode, } diff --git a/src/MethodCheck.Core/Data/MethodData.cs b/src/MethodCheck.Core/Data/MethodData.cs index b584fa8..d436260 100644 --- a/src/MethodCheck.Core/Data/MethodData.cs +++ b/src/MethodCheck.Core/Data/MethodData.cs @@ -1,21 +1,20 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. using System.Collections.Immutable; -namespace MethodCheck.Core.Data +namespace MethodCheck.Core.Data; + +public sealed class MethodData( + MetadataToken localsToken, + int maxStack, + int codeSize, + MethodDataFlags flags, + ImmutableArray instructions, + ImmutableArray dataSections) { - public sealed class MethodData( - MetadataToken localsToken, - int maxStack, - int codeSize, - MethodDataFlags flags, - ImmutableArray instructions, - ImmutableArray dataSections) - { - public MetadataToken LocalsToken { get; } = localsToken; - public int MaxStack { get; } = maxStack; - public int CodeSize { get; } = codeSize; - public MethodDataFlags Flags { get; } = flags; - public ImmutableArray Instructions { get; } = instructions; - public ImmutableArray DataSections { get; } = dataSections; - } + public MetadataToken LocalsToken { get; } = localsToken; + public int MaxStack { get; } = maxStack; + public int CodeSize { get; } = codeSize; + public MethodDataFlags Flags { get; } = flags; + public ImmutableArray Instructions { get; } = instructions; + public ImmutableArray DataSections { get; } = dataSections; } diff --git a/src/MethodCheck.Core/Data/MethodDataFlags.cs b/src/MethodCheck.Core/Data/MethodDataFlags.cs index cdfa98f..a15b0d1 100644 --- a/src/MethodCheck.Core/Data/MethodDataFlags.cs +++ b/src/MethodCheck.Core/Data/MethodDataFlags.cs @@ -1,14 +1,14 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. using System; -namespace MethodCheck.Core.Data -{ +namespace MethodCheck.Core.Data; + #pragma warning disable CA1711 // Identifiers should not have incorrect suffix - [Flags] - public enum MethodDataFlags - { - None = 0, - InitFields = 1 << 0, - } -#pragma warning restore CA1711 // Identifiers should not have incorrect suffix +[Flags] +public enum MethodDataFlags +{ + None = 0, + InitFields = 1 << 0, } +#pragma warning restore CA1711 // Identifiers should not have incorrect suffix + diff --git a/src/MethodCheck.Core/Data/MethodDataSection.cs b/src/MethodCheck.Core/Data/MethodDataSection.cs index a3e0d1a..87e1313 100644 --- a/src/MethodCheck.Core/Data/MethodDataSection.cs +++ b/src/MethodCheck.Core/Data/MethodDataSection.cs @@ -1,10 +1,9 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. using System.Collections.Immutable; -namespace MethodCheck.Core.Data +namespace MethodCheck.Core.Data; + +public sealed class MethodDataSection(ImmutableArray exceptionHandlers) { - public sealed class MethodDataSection(ImmutableArray exceptionHandlers) - { - public ImmutableArray ExceptionHandlers { get; } = exceptionHandlers; - } + public ImmutableArray ExceptionHandlers { get; } = exceptionHandlers; } diff --git a/src/MethodCheck.Core/Data/Sections/BaseSection.cs b/src/MethodCheck.Core/Data/Sections/BaseSection.cs index bf907cf..83faf54 100644 --- a/src/MethodCheck.Core/Data/Sections/BaseSection.cs +++ b/src/MethodCheck.Core/Data/Sections/BaseSection.cs @@ -1,8 +1,7 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. -namespace MethodCheck.Core.Data +namespace MethodCheck.Core.Data; + +public abstract class BaseSection(ILRange range) { - public abstract class BaseSection(ILRange range) - { - public ILRange Range { get; } = range; - } + public ILRange Range { get; } = range; } diff --git a/src/MethodCheck.Core/Data/Sections/CannotGenerateSectionException.cs b/src/MethodCheck.Core/Data/Sections/CannotGenerateSectionException.cs index 0c1017b..df7d253 100644 --- a/src/MethodCheck.Core/Data/Sections/CannotGenerateSectionException.cs +++ b/src/MethodCheck.Core/Data/Sections/CannotGenerateSectionException.cs @@ -1,22 +1,21 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. using System; -namespace MethodCheck.Core.Data.Sections +namespace MethodCheck.Core.Data.Sections; + +public sealed class CannotGenerateSectionException : Exception { - public sealed class CannotGenerateSectionException : Exception + public CannotGenerateSectionException() { - public CannotGenerateSectionException() - { - } + } - public CannotGenerateSectionException(string message) - : base(message) - { - } + public CannotGenerateSectionException(string message) + : base(message) + { + } - public CannotGenerateSectionException(string message, Exception innerException) - : base(message, innerException) - { - } + public CannotGenerateSectionException(string message, Exception innerException) + : base(message, innerException) + { } } diff --git a/src/MethodCheck.Core/Data/Sections/HandlerBlock.cs b/src/MethodCheck.Core/Data/Sections/HandlerBlock.cs index 3f529af..ea13d99 100644 --- a/src/MethodCheck.Core/Data/Sections/HandlerBlock.cs +++ b/src/MethodCheck.Core/Data/Sections/HandlerBlock.cs @@ -1,27 +1,26 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. using System.Reflection; -namespace MethodCheck.Core.Data +namespace MethodCheck.Core.Data; + +public sealed class HandlerBlock { - public sealed class HandlerBlock + public HandlerBlock(ExceptionHandlingClauseOptions type, MetadataToken exceptionType, BaseSection handlerSection) { - public HandlerBlock(ExceptionHandlingClauseOptions type, MetadataToken exceptionType, BaseSection handlerSection) - { - Type = type; - ExceptionType = exceptionType; - HandlerSection = handlerSection; - } - - public HandlerBlock(ExceptionHandlingClauseOptions type, BaseSection filterSection, BaseSection handlerSection) - { - Type = type; - FilterSection = filterSection; - HandlerSection = handlerSection; - } + Type = type; + ExceptionType = exceptionType; + HandlerSection = handlerSection; + } - public ExceptionHandlingClauseOptions Type { get; } - public BaseSection? FilterSection { get; } - public MetadataToken ExceptionType { get; } - public BaseSection HandlerSection { get; } + public HandlerBlock(ExceptionHandlingClauseOptions type, BaseSection filterSection, BaseSection handlerSection) + { + Type = type; + FilterSection = filterSection; + HandlerSection = handlerSection; } + + public ExceptionHandlingClauseOptions Type { get; } + public BaseSection? FilterSection { get; } + public MetadataToken ExceptionType { get; } + public BaseSection HandlerSection { get; } } diff --git a/src/MethodCheck.Core/Data/Sections/ILSection.cs b/src/MethodCheck.Core/Data/Sections/ILSection.cs index 7ba7cd9..6320207 100644 --- a/src/MethodCheck.Core/Data/Sections/ILSection.cs +++ b/src/MethodCheck.Core/Data/Sections/ILSection.cs @@ -1,7 +1,6 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. -namespace MethodCheck.Core.Data +namespace MethodCheck.Core.Data; + +public sealed class ILSection(ILRange range) : BaseSection(range) { - public sealed class ILSection(ILRange range) : BaseSection(range) - { - } } diff --git a/src/MethodCheck.Core/Data/Sections/SectionFactory.cs b/src/MethodCheck.Core/Data/Sections/SectionFactory.cs index 0dcf1d1..4318c52 100644 --- a/src/MethodCheck.Core/Data/Sections/SectionFactory.cs +++ b/src/MethodCheck.Core/Data/Sections/SectionFactory.cs @@ -5,223 +5,222 @@ using System.Reflection; using MethodCheck.Core.Data.Sections; -namespace MethodCheck.Core.Data +namespace MethodCheck.Core.Data; + +public static class SectionFactory { - public static class SectionFactory + // Creates a section from the provided values, assuming the handlers are ordered correctly. + public static BaseSection Create(ILRange range, IEnumerable handlers) { - // Creates a section from the provided values, assuming the handlers are ordered correctly. - public static BaseSection Create(ILRange range, IEnumerable handlers) + ArgumentNullException.ThrowIfNull(handlers); + + var generator = Builder.New(); + + foreach (var handler in handlers) { - ArgumentNullException.ThrowIfNull(handlers); + generator.Add(handler); + } - var generator = Builder.New(); + var result = generator.CreateSection(range); + generator.VerifyEmpty(); + return result; + } - foreach (var handler in handlers) - { - generator.Add(handler); - } + readonly struct Builder + { + public static Builder New() => new(new List()); - var result = generator.CreateSection(range); - generator.VerifyEmpty(); - return result; + Builder(List pendingTryBlocks) + { + _pendingTryBlocks = pendingTryBlocks; } - readonly struct Builder + public void Add(ExceptionHandler handler) { - public static Builder New() => new(new List()); + var handlerBlock = CreateHandlerBlock(handler); + var handlers = FindHandlersMatchingTryBlock(handler.TryRange); + handlers.Add(handlerBlock); + } - Builder(List pendingTryBlocks) - { - _pendingTryBlocks = pendingTryBlocks; - } + public BaseSection CreateSection(ILRange range) + { + var sections = ExtractSectionsInRange(range); - public void Add(ExceptionHandler handler) + if (sections.Count == 0) { - var handlerBlock = CreateHandlerBlock(handler); - var handlers = FindHandlersMatchingTryBlock(handler.TryRange); - handlers.Add(handlerBlock); + return new ILSection(range); } - - public BaseSection CreateSection(ILRange range) + else if (sections.Count == 1 && sections[0].Range == range) { - var sections = ExtractSectionsInRange(range); + return sections[0]; + } - if (sections.Count == 0) - { - return new ILSection(range); - } - else if (sections.Count == 1 && sections[0].Range == range) - { - return sections[0]; - } + sections.Sort((x, y) => x.Range.Offset.CompareTo(y.Range.Offset)); + return CreateSequenceSection(range, sections); + } - sections.Sort((x, y) => x.Range.Offset.CompareTo(y.Range.Offset)); - return CreateSequenceSection(range, sections); - } + HandlerBlock CreateHandlerBlock(ExceptionHandler handler) + { + var handlerSection = CreateSection(handler.HandlerRange); - HandlerBlock CreateHandlerBlock(ExceptionHandler handler) + if (handler.Type == ExceptionHandlingClauseOptions.Filter) { - var handlerSection = CreateSection(handler.HandlerRange); - - if (handler.Type == ExceptionHandlingClauseOptions.Filter) - { - var filterStart = new Label(handler.FilterOrType); - var filterRange = new ILRange(filterStart, handler.HandlerRange.Offset - filterStart); + var filterStart = new Label(handler.FilterOrType); + var filterRange = new ILRange(filterStart, handler.HandlerRange.Offset - filterStart); - return new HandlerBlock( - handler.Type, - CreateSection(filterRange), - handlerSection); - } - else - { - return new HandlerBlock( - handler.Type, - new MetadataToken(handler.FilterOrType), - handlerSection); - } + return new HandlerBlock( + handler.Type, + CreateSection(filterRange), + handlerSection); } - - static BaseSection CreateSequenceSection(ILRange range, List sections) + else { - var builder = ImmutableArray.CreateBuilder(); - var offset = range.Offset; + return new HandlerBlock( + handler.Type, + new MetadataToken(handler.FilterOrType), + handlerSection); + } + } - foreach (var section in sections) - { - if (section.Range.Offset > offset) - { - builder.Add(new ILSection(new ILRange(offset, section.Range.Offset - offset))); - } + static BaseSection CreateSequenceSection(ILRange range, List sections) + { + var builder = ImmutableArray.CreateBuilder(); + var offset = range.Offset; - builder.Add(section); - offset = End(section.Range); + foreach (var section in sections) + { + if (section.Range.Offset > offset) + { + builder.Add(new ILSection(new ILRange(offset, section.Range.Offset - offset))); } - var end = End(range); + builder.Add(section); + offset = End(section.Range); + } - if (offset < end) - { - builder.Add(new ILSection(new ILRange(offset, end - offset))); - } + var end = End(range); - return new SequenceSection(range, builder.ToImmutable()); + if (offset < end) + { + builder.Add(new ILSection(new ILRange(offset, end - offset))); } - List ExtractSectionsInRange(ILRange range) + return new SequenceSection(range, builder.ToImmutable()); + } + + List ExtractSectionsInRange(ILRange range) + { + var builder = new List(); + var write = 0; + + for (var read = 0; read < _pendingTryBlocks.Count; read++) { - var builder = new List(); - var write = 0; + var item = _pendingTryBlocks[read]; - for (var read = 0; read < _pendingTryBlocks.Count; read++) + if (range.Contains(item.TryRange)) { - var item = _pendingTryBlocks[read]; + var newItem = item.Complete(); - if (range.Contains(item.TryRange)) + if (!range.Contains(newItem.Range)) { - var newItem = item.Complete(); + throw new CannotGenerateSectionException(); + } - if (!range.Contains(newItem.Range)) + foreach (var other in builder) + { + if (newItem.Range.Overlaps(other.Range)) { throw new CannotGenerateSectionException(); } - - foreach (var other in builder) - { - if (newItem.Range.Overlaps(other.Range)) - { - throw new CannotGenerateSectionException(); - } - } - - builder.Add(newItem); } - else - { - if (write != read) - { - _pendingTryBlocks[write] = item; - } - write++; - } + builder.Add(newItem); } - - _pendingTryBlocks.RemoveRange(write, _pendingTryBlocks.Count - write); - return builder; - } - - ImmutableArray.Builder FindHandlersMatchingTryBlock(ILRange range) - { - foreach (var item in _pendingTryBlocks) + else { - if (item.TryRange == range) + if (write != read) { - return item.Handlers; + _pendingTryBlocks[write] = item; } - } - var builder = new TryBuilder(range, CreateSection(range)); - _pendingTryBlocks.Add(builder); - return builder.Handlers; + write++; + } } - static Label End(ILRange range) => range.Offset + range.Length; + _pendingTryBlocks.RemoveRange(write, _pendingTryBlocks.Count - write); + return builder; + } - public void VerifyEmpty() + ImmutableArray.Builder FindHandlersMatchingTryBlock(ILRange range) + { + foreach (var item in _pendingTryBlocks) { - if (_pendingTryBlocks.Count > 0) + if (item.TryRange == range) { - throw new CannotGenerateSectionException(); + return item.Handlers; } } - readonly List _pendingTryBlocks; + var builder = new TryBuilder(range, CreateSection(range)); + _pendingTryBlocks.Add(builder); + return builder.Handlers; + } - readonly struct TryBuilder(ILRange tryRange, BaseSection trySection) - { - public ILRange TryRange { get; } = tryRange; - public BaseSection TrySection { get; } = trySection; - public ImmutableArray.Builder Handlers { get; } = ImmutableArray.CreateBuilder(); + static Label End(ILRange range) => range.Offset + range.Length; - public TryBlockSection Complete() - { - var handlers = Handlers.ToImmutable(); - handlers.Sort((x, y) => x.HandlerSection.Range.Offset.CompareTo(y.HandlerSection.Range.Offset)); + public void VerifyEmpty() + { + if (_pendingTryBlocks.Count > 0) + { + throw new CannotGenerateSectionException(); + } + } - var end = End(TrySection.Range); + readonly List _pendingTryBlocks; - foreach (var handler in handlers) - { - var handlerEnd = End(handler.HandlerSection.Range); + readonly struct TryBuilder(ILRange tryRange, BaseSection trySection) + { + public ILRange TryRange { get; } = tryRange; + public BaseSection TrySection { get; } = trySection; + public ImmutableArray.Builder Handlers { get; } = ImmutableArray.CreateBuilder(); - if (handler.FilterSection != null) - { - var filterRange = handler.FilterSection.Range; + public TryBlockSection Complete() + { + var handlers = Handlers.ToImmutable(); + handlers.Sort((x, y) => x.HandlerSection.Range.Offset.CompareTo(y.HandlerSection.Range.Offset)); - if (filterRange.Offset != end) - { - throw new CannotGenerateSectionException(); - } + var end = End(TrySection.Range); - end = End(filterRange); - } + foreach (var handler in handlers) + { + var handlerEnd = End(handler.HandlerSection.Range); - var handlerRange = handler.HandlerSection.Range; + if (handler.FilterSection != null) + { + var filterRange = handler.FilterSection.Range; - if (handlerRange.Offset != end) + if (filterRange.Offset != end) { throw new CannotGenerateSectionException(); } - end = End(handlerRange); + end = End(filterRange); } - return new TryBlockSection( - new ILRange(TryRange.Offset, end - TryRange.Offset), - TrySection, - handlers); + var handlerRange = handler.HandlerSection.Range; + + if (handlerRange.Offset != end) + { + throw new CannotGenerateSectionException(); + } + + end = End(handlerRange); } + + return new TryBlockSection( + new ILRange(TryRange.Offset, end - TryRange.Offset), + TrySection, + handlers); } } } diff --git a/src/MethodCheck.Core/Data/Sections/SequenceSection.cs b/src/MethodCheck.Core/Data/Sections/SequenceSection.cs index 5922801..6c09ae0 100644 --- a/src/MethodCheck.Core/Data/Sections/SequenceSection.cs +++ b/src/MethodCheck.Core/Data/Sections/SequenceSection.cs @@ -1,10 +1,9 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. using System.Collections.Immutable; -namespace MethodCheck.Core.Data.Sections +namespace MethodCheck.Core.Data.Sections; + +public sealed class SequenceSection(ILRange range, ImmutableArray sections) : BaseSection(range) { - public sealed class SequenceSection(ILRange range, ImmutableArray sections) : BaseSection(range) - { - public ImmutableArray Sections { get; } = sections; - } + public ImmutableArray Sections { get; } = sections; } diff --git a/src/MethodCheck.Core/Data/Sections/TryBlockSection.cs b/src/MethodCheck.Core/Data/Sections/TryBlockSection.cs index 1407771..3436199 100644 --- a/src/MethodCheck.Core/Data/Sections/TryBlockSection.cs +++ b/src/MethodCheck.Core/Data/Sections/TryBlockSection.cs @@ -1,15 +1,14 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. using System.Collections.Immutable; -namespace MethodCheck.Core.Data +namespace MethodCheck.Core.Data; + +public sealed class TryBlockSection( + ILRange range, + BaseSection tryBlock, + ImmutableArray handlerBlocks) + : BaseSection(range) { - public sealed class TryBlockSection( - ILRange range, - BaseSection tryBlock, - ImmutableArray handlerBlocks) - : BaseSection(range) - { - public BaseSection TryBlock { get; } = tryBlock; - public ImmutableArray HandlerBlocks { get; } = handlerBlocks; - } + public BaseSection TryBlock { get; } = tryBlock; + public ImmutableArray HandlerBlocks { get; } = handlerBlocks; } diff --git a/src/MethodCheck.Core/Data/Values/ILRange.cs b/src/MethodCheck.Core/Data/Values/ILRange.cs index 0a05e18..24a533f 100644 --- a/src/MethodCheck.Core/Data/Values/ILRange.cs +++ b/src/MethodCheck.Core/Data/Values/ILRange.cs @@ -1,30 +1,29 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. using System; -namespace MethodCheck.Core.Data +namespace MethodCheck.Core.Data; + +public readonly struct ILRange(Label offset, int length) : IEquatable { - public readonly struct ILRange(Label offset, int length) : IEquatable - { - public Label Offset { get; } = offset; - public int Length { get; } = length; + public Label Offset { get; } = offset; + public int Length { get; } = length; - public override int GetHashCode() + public override int GetHashCode() + { + unchecked { - unchecked - { - var tmp = (uint)Offset.GetHashCode(); - tmp = ((tmp << 16) | (tmp >> 16)) ^ (uint)Length; - return (int)tmp; - } + var tmp = (uint)Offset.GetHashCode(); + tmp = ((tmp << 16) | (tmp >> 16)) ^ (uint)Length; + return (int)tmp; } + } - public override bool Equals(object? obj) => obj is ILRange range && Equals(range); - public bool Equals(ILRange other) => Offset == other.Offset && Length == other.Length; - public bool Contains(ILRange range) => range.Offset >= Offset && (range.Offset + range.Length - Offset) <= Length; - public bool Overlaps(ILRange range) => range.Offset < Offset + Length && Offset < range.Offset + range.Length; - public override string ToString() => $"{Offset} ({Length})"; + public override bool Equals(object? obj) => obj is ILRange range && Equals(range); + public bool Equals(ILRange other) => Offset == other.Offset && Length == other.Length; + public bool Contains(ILRange range) => range.Offset >= Offset && (range.Offset + range.Length - Offset) <= Length; + public bool Overlaps(ILRange range) => range.Offset < Offset + Length && Offset < range.Offset + range.Length; + public override string ToString() => $"{Offset} ({Length})"; - public static bool operator ==(ILRange range1, ILRange range2) => range1.Equals(range2); - public static bool operator !=(ILRange range1, ILRange range2) => !range1.Equals(range2); - } + public static bool operator ==(ILRange range1, ILRange range2) => range1.Equals(range2); + public static bool operator !=(ILRange range1, ILRange range2) => !range1.Equals(range2); } diff --git a/src/MethodCheck.Core/Data/Values/IncompleteArgument.cs b/src/MethodCheck.Core/Data/Values/IncompleteArgument.cs index dc22623..0549099 100644 --- a/src/MethodCheck.Core/Data/Values/IncompleteArgument.cs +++ b/src/MethodCheck.Core/Data/Values/IncompleteArgument.cs @@ -1,14 +1,13 @@ // Copyright (c) Brian Reichle. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. -namespace MethodCheck.Core.Data -{ - sealed class IncompleteArgument - { - public static IncompleteArgument Value { get; } = new IncompleteArgument(); +namespace MethodCheck.Core.Data; - IncompleteArgument() - { - } +sealed class IncompleteArgument +{ + public static IncompleteArgument Value { get; } = new IncompleteArgument(); - public override string ToString() => "??"; + IncompleteArgument() + { } + + public override string ToString() => "??"; } diff --git a/src/MethodCheck.Core/Data/Values/Label.cs b/src/MethodCheck.Core/Data/Values/Label.cs index fbd7673..fd3ec9f 100644 --- a/src/MethodCheck.Core/Data/Values/Label.cs +++ b/src/MethodCheck.Core/Data/Values/Label.cs @@ -3,29 +3,28 @@ using System.Diagnostics; using System.Globalization; -namespace MethodCheck.Core.Data +namespace MethodCheck.Core.Data; + +public readonly struct Label(int offset) : IEquatable