Upsilon/Upsilon/Diagnostics.cs

144 lines
4.5 KiB
C#

using System.Collections.Generic;
using Upsilon.BaseTypes;
using Upsilon.Parser;
using Upsilon.Text;
namespace Upsilon
{
public class Diagnostics
{
public SourceText ScriptString { get; }
public readonly List<DiagnosticsMessage> Messages = new List<DiagnosticsMessage>();
public Diagnostics(SourceText scriptString)
{
ScriptString = scriptString;
}
public void Log(DiagnosticLevel level, string message, TextSpan location)
{
Messages.Add(new DiagnosticsMessage(this, level, message, location));
}
public void LogError(string message, TextSpan location)
{
Log(DiagnosticLevel.Error, message, location);
}
public void LogBadCharacter(TextSpan location, SyntaxKind expectedToken, SyntaxKind currentKind)
{
LogError($"Invalid character found. Expected: '{expectedToken}', Got: '{currentKind}'", location);
}
public void LogBadCharacter(TextSpan location, SyntaxKind expectedToken)
{
LogError($"Invalid character found. Expected: '{expectedToken}'", location);
}
public void LogBadCharacter(TextSpan location)
{
LogError($"Invalid character found.", location);
}
public void LogUnknownVariable(TextSpan span, string variable)
{
LogError($"Unknown variable '{variable}'", span);
}
public void LogNullReferenceError(TextSpan span)
{
LogError($"Null Reference Encountered", span);
}
public void LogUnknownType(TextSpan eSpan)
{
LogError($"Unknown Type found", eSpan);
}
public void LogUnknownBinaryOperator(TextSpan eSpan, SyntaxKind text, Type leftType, Type rightType)
{
LogError($"No binary operator {text} found for types '{leftType}' and '{rightType}'", eSpan);
}
public void LogUnknownUnaryOperator(TextSpan eSpan, SyntaxKind text, Type inType)
{
LogError($"No unary operator {text} found for type '{inType}'", eSpan);
}
public void LogCannotConvert(Type actualType, Type expectedType, TextSpan span)
{
LogError($"Cannot convert type '{actualType}' to '{expectedType}'", span);
}
public void LogInvalidIndexExpression(Type expressionType, Type indexType, TextSpan span)
{
LogError($"Cannot index type '{expressionType}' with type '{indexType}'", span);
}
}
public class DiagnosticsMessage
{
public Diagnostics Diagnostics { get; }
private readonly DiagnosticLevel _diagnosticLevel;
public string Message { get; }
public TextSpan Span { get; }
public DiagnosticsMessage(Diagnostics diagnostics, DiagnosticLevel diagnosticLevel, string message, TextSpan span)
{
_diagnosticLevel = diagnosticLevel;
Diagnostics = diagnostics;
Message = message;
Span = span;
}
public override string ToString()
{
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);
return $"{Message} at ({linePos.Line}, {linePos.Pos})\n{Diagnostics.ScriptString.GetSpan(Span)}";
}
public string GetDiagnosticPosition()
{
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);
return $"({linePos.Line},{linePos.Pos})";
}
public string LineBeforeError()
{
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);
var lineIndex = Diagnostics.ScriptString.GetLineStartPos(linePos.Line);
return Diagnostics.ScriptString.GetSpan(lineIndex, linePos.Pos);
}
public string BeforeError(int i = 5)
{
return Diagnostics.ScriptString.GetSpan(Span.Start - i, i);
}
public string AtError()
{
return Diagnostics.ScriptString.GetSpan(Span);
}
public string LineAfterError()
{
var linePos = Diagnostics.ScriptString.GetLinePosition(Span.Start);
var lineInfo = Diagnostics.ScriptString.GetLineInfo(linePos.Line);
return Diagnostics.ScriptString.GetSpan(Span.End, lineInfo.End - Span.End);
}
public string AfterError(int i = 5)
{
return Diagnostics.ScriptString.GetSpan(Span.Start + Span.Length, i);
}
}
public enum DiagnosticLevel
{
Information,
Warning,
Error,
}
}