<commit_before>using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

namespace CppSharp.AST
{
    /// <summary>
    /// Represents a source code unit.
    /// </summary>
    [DebuggerDisplay("File = {FileName}, Ignored = {Ignore}")]
    public class TranslationUnit : Namespace
    {
        public TranslationUnit()
        {
            Macros = new List<MacroDefinition>();
            Access = AccessSpecifier.Public;
        }

        public TranslationUnit(string file) : this()
        {
            FilePath = file;
        }

        /// Contains the macros present in the unit.
        public List<MacroDefinition> Macros;

        public Module Module { get; set; }

        public bool IsSystemHeader { get; set; }

        public bool IsValid => FilePath != "<invalid>";

        /// Contains the path to the file.
        public string FilePath;

        private string fileName;
        private string fileNameWithoutExtension;

        /// Contains the name of the file.
        public string FileName
        {
            get { return !IsValid ? FilePath : fileName ?? (fileName = Path.GetFileName(FilePath)); }
        }

        /// Contains the name of the module.
        public string FileNameWithoutExtension
        {
            get
            {
                return fileNameWithoutExtension ??
                    (fileNameWithoutExtension = Path.GetFileNameWithoutExtension(FileName));
            }
        }

        /// Contains the include path.
        public string IncludePath;

        private string fileRelativeDirectory;
        private string fileRelativePath;

        public string FileRelativeDirectory
        {
            get
            {
                if (fileRelativeDirectory != null) return fileRelativeDirectory;
                var path = IncludePath.Replace('\\', '/');
                var index = path.LastIndexOf('/');
                return fileRelativeDirectory = path.Substring(0, index);
            }
        }

        public string FileRelativePath
        {
            get
            {
                return fileRelativePath ??
                    (fileRelativePath = Path.Combine(FileRelativeDirectory, FileName));
            }
        }

        public override T Visit<T>(IDeclVisitor<T> visitor)
        {
            return visitor.VisitTranslationUnit(this);
        }
    }
}<commit_msg>Fix TranslationUnit.FileRelativePath for invalid units.<commit_after>using System.Collections.Generic;
using System.Diagnostics;
using System.IO;

namespace CppSharp.AST
{
    /// <summary>
    /// Represents a source code unit.
    /// </summary>
    [DebuggerDisplay("File = {FileName}, Ignored = {Ignore}")]
    public class TranslationUnit : Namespace
    {
        public TranslationUnit()
        {
            Macros = new List<MacroDefinition>();
            Access = AccessSpecifier.Public;
        }

        public TranslationUnit(string file) : this()
        {
            FilePath = file;
        }

        /// Contains the macros present in the unit.
        public List<MacroDefinition> Macros;

        public Module Module { get; set; }

        public bool IsSystemHeader { get; set; }

        public bool IsValid => FilePath != "<invalid>";

        /// Contains the path to the file.
        public string FilePath;

        private string fileName;
        private string fileNameWithoutExtension;

        /// Contains the name of the file.
        public string FileName
        {
            get { return !IsValid ? FilePath : fileName ?? (fileName = Path.GetFileName(FilePath)); }
        }

        /// Contains the name of the module.
        public string FileNameWithoutExtension
        {
            get
            {
                return fileNameWithoutExtension ??
                    (fileNameWithoutExtension = Path.GetFileNameWithoutExtension(FileName));
            }
        }

        /// Contains the include path.
        public string IncludePath;

        private string fileRelativeDirectory;
        private string fileRelativePath;

        public string FileRelativeDirectory
        {
            get
            {
                if (fileRelativeDirectory != null) return fileRelativeDirectory;
                var path = IncludePath.Replace('\\', '/');
                var index = path.LastIndexOf('/');
                return fileRelativeDirectory = path.Substring(0, index);
            }
        }

        public string FileRelativePath
        {
            get
            {
                if (!IsValid) return string.Empty;
                return fileRelativePath ??
                    (fileRelativePath = Path.Combine(FileRelativeDirectory, FileName));
            }
        }

        public override T Visit<T>(IDeclVisitor<T> visitor)
        {
            return visitor.VisitTranslationUnit(this);
        }
    }
}
{'fraction_non_alphanumeric': 0.08468320688948124, 'fraction_numerical': 0.0004100881689563256, 'mean_word_length': 1.6802197802197802, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 19, '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': '4008845', 'n_tokens_mistral': 1174, 'n_tokens_neox': 1122, 'n_words': 316}