diff --git a/Linguini.Bundle/Errors/FluentError.cs b/Linguini.Bundle/Errors/FluentError.cs index b12e3f8..ad957d4 100644 --- a/Linguini.Bundle/Errors/FluentError.cs +++ b/Linguini.Bundle/Errors/FluentError.cs @@ -2,10 +2,13 @@ using Linguini.Syntax.Ast; using Linguini.Syntax.Parser.Error; +// ReSharper disable UnusedMember.Global +// ReSharper disable MemberCanBePrivate.Global + namespace Linguini.Bundle.Errors { /// - /// Base record for Linguini Fluent errors. + /// Provides base record for Linguini's Fluent related errors. /// public abstract record FluentError { @@ -24,10 +27,12 @@ public abstract record FluentError return null; } + + /// - /// String represntation of the error. + /// String representation of the error. /// - /// + /// Error represented as string public override string ToString() => $"Error (${ErrorKind()})"; } @@ -48,18 +53,25 @@ public record ErrorSpan(int Row, int StartSpan, int EndSpan, int StartMark, int /// public record OverrideFluentError : FluentError { - private readonly string _id; private readonly EntryKind _kind; + private readonly string? _location; /// /// Id of term or message that was overriden. /// - public string Id => _id; + public string Id { get; } - public OverrideFluentError(string id, EntryKind kind) + /// + /// Constructs an + /// + /// Duplicated identifier + /// Enumeration showing what kind of identifier was duplicate MESSAGE | TERM | FUNCTION + /// Location where the error originated. Due to backwards compatibility it defaults to null + public OverrideFluentError(string id, EntryKind kind, string? location = null) { - _id = id; + Id = id; _kind = kind; + _location = location; } /// @@ -68,90 +80,101 @@ public override ErrorType ErrorKind() return ErrorType.Overriding; } + /// public override string ToString() { - return $"For id:{_id} already exist entry of type: {_kind.ToString()}"; + return $"For id:{Id} already exist entry of type: {_kind.ToString()}"; } } + /// + /// + /// public record ResolverFluentError : FluentError { private readonly string _description; private readonly ErrorType _kind; + private readonly string? _location; - private ResolverFluentError(string desc, ErrorType kind) + private ResolverFluentError(string desc, ErrorType kind, string? location) { _description = desc; _kind = kind; + _location = location; } + /// public override ErrorType ErrorKind() { return _kind; } + + /// public override string ToString() { return _description; } - public static ResolverFluentError NoValue(ReadOnlyMemory idName) + public static ResolverFluentError NoValue(ReadOnlyMemory idName, string? location = null) { - return new($"No value: {idName.Span.ToString()}", ErrorType.NoValue); + return new($"No value: {idName.Span.ToString()}", ErrorType.NoValue, location); } - public static ResolverFluentError NoValue(string pattern) + public static ResolverFluentError NoValue(string pattern, string? location = null) { - return new($"No value: {pattern}", ErrorType.NoValue); + return new($"No value: {pattern}", ErrorType.NoValue, location); } - public static ResolverFluentError UnknownVariable(VariableReference outType) + public static ResolverFluentError UnknownVariable(VariableReference outType, string? location = null) { - return new($"Unknown variable: ${outType.Id}", ErrorType.Reference); + return new($"Unknown variable: ${outType.Id}", ErrorType.Reference, location); } - public static ResolverFluentError TooManyPlaceables() + public static ResolverFluentError TooManyPlaceables(string? location = null) { - return new("Too many placeables", ErrorType.TooManyPlaceables); + return new("Too many placeables", ErrorType.TooManyPlaceables, location); } - public static ResolverFluentError Reference(IInlineExpression self) + public static ResolverFluentError Reference(IInlineExpression self, string? location = null) { return self switch { - FunctionReference funcRef => new($"Unknown function: {funcRef.Id}()", ErrorType.Reference), + FunctionReference funcRef => new($"Unknown function: {funcRef.Id}()", ErrorType.Reference, location), MessageReference msgRef when msgRef.Attribute == null => new($"Unknown message: {msgRef.Id}", - ErrorType.Reference), + ErrorType.Reference, location), MessageReference msgRef => new($"Unknown attribute: {msgRef.Id}.{msgRef.Attribute}", - ErrorType.Reference), + ErrorType.Reference, location), TermReference termReference when termReference.Attribute == null => new( - $"Unknown term: -{termReference.Id}", ErrorType.Reference), + $"Unknown term: -{termReference.Id}", ErrorType.Reference, location), TermReference termReference => new($"Unknown attribute: -{termReference.Id}.{termReference.Attribute}", - ErrorType.Reference), - VariableReference varRef => new($"Unknown variable: ${varRef.Id}", ErrorType.Reference), + ErrorType.Reference, location), + VariableReference varRef => new($"Unknown variable: ${varRef.Id}", ErrorType.Reference, location), _ => throw new ArgumentException($"Expected reference got ${self.GetType()}") }; } - public static ResolverFluentError Cyclic(Pattern pattern) + public static ResolverFluentError Cyclic(Pattern pattern, string? location = null) { - return new($"Cyclic reference in {pattern.Stringify()} detected!", ErrorType.Cyclic); + return new($"Cyclic reference in {pattern.Stringify()} detected!", ErrorType.Cyclic, location); } - public static ResolverFluentError MissingDefault() + public static ResolverFluentError MissingDefault(string? location = null) { - return new("No default", ErrorType.MissingDefault); + return new("No default", ErrorType.MissingDefault, location); } } public record ParserFluentError : FluentError { private readonly ParseError _error; + private readonly string? _location; - private ParserFluentError(ParseError error) + private ParserFluentError(ParseError error, string? location = null) { _error = error; + _location = location; } public static ParserFluentError ParseError(ParseError parseError) @@ -159,16 +182,19 @@ public static ParserFluentError ParseError(ParseError parseError) return new(parseError); } + /// public override ErrorType ErrorKind() { return ErrorType.Parser; } + /// public override string ToString() { return _error.Message; } + /// public override ErrorSpan? GetSpan() { if (_error.Slice == null) @@ -179,6 +205,9 @@ public override string ToString() } } + /// + /// Enumeration showing which kind of Entry was duplicated. + /// public enum EntryKind : byte { Message, @@ -190,12 +219,12 @@ public static class EntryHelper { public static EntryKind ToKind(this IEntry self) { - if (self is AstTerm) + return self switch { - return EntryKind.Term; - } - - return self is AstMessage ? EntryKind.Message : EntryKind.Func; + AstTerm => EntryKind.Term, + AstMessage => EntryKind.Message, + _ => EntryKind.Func + }; } } @@ -209,4 +238,4 @@ public enum ErrorType : byte Overriding, MissingDefault } -} +} \ No newline at end of file