<commit_before>using Uno;
using Uno.Compiler;
using Uno.Collections;

namespace Fuse
{
	public enum DiagnosticType
	{
		UserSuccess,
		UserError,
		UserWarning,
		InternalError,
		Deprecated,
		Unsupported,
		PerformanceWarning,
	}
	
	/** @hide */
	public interface ISourceLocation
	{
		int SourceLineNumber { get; }
		string SourceFileName { get; }
		/* Return the nearest ISourceLocation that is known. This should walk up the tree of nodes until a UX source node is found. */
		ISourceLocation SourceNearest { get; }
	}
	
	/**
		Assume that any of these properties can be null (except Type).
	*/
	public class Diagnostic
	{
		public readonly DiagnosticType Type;
		public readonly string Message;
		public readonly object SourceObject;
		public readonly string FilePath;
		public readonly int LineNumber;
		public readonly string MemberName;
		public readonly Exception Exception;

		internal bool IsTemporalWarning;
		
		internal Uno.Diagnostics.DebugMessageType UnoType
		{
			get
			{
				switch (Type)
				{
					case DiagnosticType.UserSuccess:
						return Uno.Diagnostics.DebugMessageType.Information;

					case DiagnosticType.UserWarning:
					case DiagnosticType.Deprecated:
					case DiagnosticType.Unsupported:
					case DiagnosticType.PerformanceWarning:
						return Uno.Diagnostics.DebugMessageType.Warning;

					case DiagnosticType.UserError:
					case DiagnosticType.InternalError:
						return Uno.Diagnostics.DebugMessageType.Error;

					default:
						throw new Exception("invalid Type: " + Type);
				}
			}
		}

		public Diagnostic(DiagnosticType type, string message, object sourceObject, string filePath, int lineNumber, string memberName, Exception exception = null)
		{
			Type = type;
			Message = message;
			SourceObject = sourceObject;
			FilePath = filePath;
			LineNumber = lineNumber;
			MemberName = memberName;
			//diagnostics only care about the source exception
			Exception = WrapException.Unwrap(exception);
		}

		public override string ToString()
		{
			return Format(true);
		}
		
		internal string Format( bool withType )
		{
			var msg = string.Empty;

			if (withType)
			{
				//use "friendlier" output for some types
				switch (Type)
				{
					case DiagnosticType.UserSuccess: msg += "Success"; break;
					case DiagnosticType.UserError: msg += "Error"; break;
					case DiagnosticType.UserWarning: msg += "Warning"; break;
					default: msg += Type; break;
				}
				msg += ": ";
			}

			if (Message != null)
				msg += Message;

			if (Exception != null)
				msg += ": " + Exception.Message;

			if (SourceObject != null)
				msg += "\n\tObject: " + SourceObject;

			var sl = SourceObject as ISourceLocation;
			if (sl != null)
				sl = sl.SourceNearest;
			if (sl != null)
			{
				if (sl != SourceObject)
					msg += "\n\tNear: " + sl;
				msg += " (" + sl.SourceFileName + ":" + sl.SourceLineNumber +")";
			}
				
			if defined(DEBUG)
			{
				if (FilePath != null)
					msg += "\n\tFuse: " + FilePath + ":" + LineNumber;
			}

			return msg;
		}
	}

	[Obsolete]
	public interface IScriptException
	{
		string FileName { get; }
		int LineNumber { get; }
	}
	
	public delegate void DiagnosticHandler( Diagnostic d );
	
	/** 
		Static API for reporting diagnostic warnings and errors for display in visual tools 
	
		The `User...` messages indicate the user (programmer) has done something wrong and needs
		to modify their code. These will most likely be displayed prominantly to the user. This should be seen
		from the point of view of a typical UX/JS user, not somebody writing Uno code.
		
		The `Internal...` messages are for situations that can't be directly attributed to a user error. They<commit_msg>capture near info at creation time<commit_after>using Uno;
using Uno.Compiler;
using Uno.Collections;

namespace Fuse
{
	public enum DiagnosticType
	{
		UserSuccess,
		UserError,
		UserWarning,
		InternalError,
		Deprecated,
		Unsupported,
		PerformanceWarning,
	}
	
	/** @hide */
	public interface ISourceLocation
	{
		int SourceLineNumber { get; }
		string SourceFileName { get; }
		/* Return the nearest ISourceLocation that is known. This should walk up the tree of nodes until a UX source node is found. */
		ISourceLocation SourceNearest { get; }
	}
	
	/**
		Assume that any of these properties can be null (except Type).
	*/
	public class Diagnostic
	{
		public readonly DiagnosticType Type;
		public readonly string Message;
		public readonly object SourceObject;
		public readonly string FilePath;
		public readonly int LineNumber;
		public readonly string MemberName;
		public readonly Exception Exception;
		
		//The "Near" information is the most recent known position in the user's code (UX) where the 
		//diagnostics originates. It maybe null.
		public readonly object NearObject;
		public readonly object NearLineNumber;
		public readonly object NearFileName;

		internal bool IsTemporalWarning;
		
		internal Uno.Diagnostics.DebugMessageType UnoType
		{
			get
			{
				switch (Type)
				{
					case DiagnosticType.UserSuccess:
						return Uno.Diagnostics.DebugMessageType.Information;

					case DiagnosticType.UserWarning:
					case DiagnosticType.Deprecated:
					case DiagnosticType.Unsupported:
					case DiagnosticType.PerformanceWarning:
						return Uno.Diagnostics.DebugMessageType.Warning;

					case DiagnosticType.UserError:
					case DiagnosticType.InternalError:
						return Uno.Diagnostics.DebugMessageType.Error;

					default:
						throw new Exception("invalid Type: " + Type);
				}
			}
		}

		public Diagnostic(DiagnosticType type, string message, object sourceObject, string filePath, int lineNumber, string memberName, Exception exception = null)
		{
			Type = type;
			Message = message;
			SourceObject = sourceObject;
			FilePath = filePath;
			LineNumber = lineNumber;
			MemberName = memberName;
			//diagnostics only care about the source exception
			Exception = WrapException.Unwrap(exception);

			// capture Near information at creation in case it changes (like unrooting) prior to being displayed
			var sl = SourceObject as ISourceLocation;
			if (sl != null)
				sl = sl.SourceNearest;
			if (sl != null)
			{
				NearObject = sl;
				NearLineNumber = sl.SourceLineNumber;
				NearFileName = sl.SourceFileName;
			}
		}

		public override string ToString()
		{
			return Format(true);
		}
		
		internal string Format( bool withType )
		{
			var msg = string.Empty;

			if (withType)
			{
				//use "friendlier" output for some types
				switch (Type)
				{
					case DiagnosticType.UserSuccess: msg += "Success"; break;
					case DiagnosticType.UserError: msg += "Error"; break;
					case DiagnosticType.UserWarning: msg += "Warning"; break;
					default: msg += Type; break;
				}
				msg += ": ";
			}

			if (Message != null)
				msg += Message;

			if (Exception != null)
				msg += ": " + Exception.Message;

			if (SourceObject != null)
				msg += "\n\tObject: " + SourceObject;

			if (NearObject != null)
			{
				if (NearObject != SourceObject)
					msg += "\n\tNear: " + NearObject;
				msg += " (" + NearFileName + ":" + NearLineNumber +")";
			}
				
			if defined(DEBUG)
			{
				if (FilePath != null)
					msg += "\n\tFuse: " + FilePath + ":" + LineNumber;
			}

			return msg;
		}
	}

	[Obsolete]
	public interface IScriptException
	{
		string FileName { get; }
		int LineNumber { get; }
	}
	
	public delegate void DiagnosticHandler( Diagnostic d );
	
	/** 
		Static API for reporting diagnostic warnings and errors for display in visual tools 
	
		The `User...` messages indicate the user (programmer) has done something wrong and needs
		to modify their code. These will most likely be displayed prominantly to the user. This should be seen
		from the point of view of a typical UX/JS user, not somebody writing Uno code.
		
		The `Internal...` messages are for situations that can't be directly attributed to a user error. They
{'fraction_non_alphanumeric': 0.08766357514928218, 'fraction_numerical': 0.0, 'mean_word_length': 3.1761273209549072, 'pattern_counts': {'":': 8, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3498424', 'n_tokens_mistral': 2771, 'n_tokens_neox': 2189, 'n_words': 763}