public SourceFile OpenInclude(string includeFilename, SourceFile currentFile)
        {
            SourceText text;

            includeFilename = includeFilename
                              .Replace('/', Path.DirectorySeparatorChar)
                              .Replace('\\', Path.DirectorySeparatorChar);

            // Check for invalid path chars.
            if (includeFilename.Any(x => Path.GetInvalidPathChars().Contains(x)))
            {
                return(null);
            }

            // If path is rooted, open it directly.
            if (Path.IsPathRooted(includeFilename))
            {
                if (_fileSystem.TryGetFile(includeFilename, out text))
                {
                    return(new SourceFile(text, currentFile));
                }
                return(null);
            }

            // Look through the hierarchy of files that included currentFile, to see if any of their
            // directories contain the include.
            var fileToCheck = currentFile;

            while (fileToCheck != null)
            {
                if (fileToCheck.FilePath != null)
                {
                    var rootFileDirectory = Path.GetDirectoryName(fileToCheck.FilePath);
                    var testFilename      = Path.Combine(rootFileDirectory, includeFilename);
                    if (_fileSystem.TryGetFile(testFilename, out text))
                    {
                        return(new SourceFile(text, currentFile));
                    }
                }
                fileToCheck = fileToCheck.IncludedBy;
            }

            // Then try additional include directories.
            foreach (var includeDirectory in _parserOptions.AdditionalIncludeDirectories)
            {
                var testFilename = Path.Combine(includeDirectory, includeFilename);
                if (_fileSystem.TryGetFile(testFilename, out text))
                {
                    return(new SourceFile(text, currentFile));
                }
            }

            return(null);
        }
        public SourceText OpenInclude(string includeFilename, string currentFilename, string rootFilename, IEnumerable <string> additionalIncludeDirectories)
        {
            SourceText text;

            // Check for invalid path chars.
            if (includeFilename.Any(x => Path.GetInvalidPathChars().Contains(x)))
            {
                return(null);
            }

            // If path is rooted, open it directly.
            if (Path.IsPathRooted(includeFilename))
            {
                _fileSystem.TryGetFile(includeFilename, out text);
                return(text);
            }

            // If current file has been saved (i.e. has a filename), try same directory as current file.
            if (currentFilename != null)
            {
                var rootFileDirectory = Path.GetDirectoryName(currentFilename);
                if (_fileSystem.TryGetFile(Path.Combine(rootFileDirectory, includeFilename), out text))
                {
                    return(text);
                }
            }

            // If this is not the root file, try same directory as root file.
            if (rootFilename != currentFilename)
            {
                var rootFileDirectory = Path.GetDirectoryName(rootFilename);
                if (_fileSystem.TryGetFile(Path.Combine(rootFileDirectory, includeFilename), out text))
                {
                    return(text);
                }
            }

            // Then try additional include directories.
            foreach (var includeDirectory in additionalIncludeDirectories)
            {
                if (_fileSystem.TryGetFile(Path.Combine(includeDirectory, includeFilename), out text))
                {
                    return(text);
                }
            }

            return(null);
        }
        public SourceFile OpenInclude(string includeFilename, SourceFile currentFile)
        {
            SourceText text;

            includeFilename = includeFilename
                              .Replace('/', Path.DirectorySeparatorChar)
                              .Replace('\\', Path.DirectorySeparatorChar);

            // Resolve virtual directory mappings.
            if (includeFilename.StartsWith(Path.DirectorySeparatorChar.ToString()))
            {
                var secondSeparatorIndex = includeFilename.IndexOf(Path.DirectorySeparatorChar, 1);
                if (secondSeparatorIndex != -1)
                {
                    var virtualDirectory = includeFilename.Substring(0, secondSeparatorIndex);
                    var remainingPath    = includeFilename.Substring(virtualDirectory.Length + 1);
                    if (_parserOptions.VirtualDirectoryMappings.TryGetValue(virtualDirectory, out var realDirectory))
                    {
                        includeFilename = Path.Combine(realDirectory, remainingPath);
                    }
                }
            }

            // Check for invalid path chars.
            if (includeFilename.Any(x => Path.GetInvalidPathChars().Contains(x)))
            {
                return(null);
            }

            // If path is rooted, open it directly.
            if (Path.IsPathRooted(includeFilename))
            {
                if (_fileSystem.TryGetFile(includeFilename, out text))
                {
                    return(new SourceFile(text, currentFile, includeFilename));
                }
                return(null);
            }

            // Look through the hierarchy of files that included currentFile, to see if any of their
            // directories contain the include.
            var fileToCheck = currentFile;

            while (fileToCheck != null)
            {
                if (fileToCheck.FilePath != null)
                {
                    var rootFileDirectory = Path.GetDirectoryName(fileToCheck.FilePath);
                    var testFilename      = Path.Combine(rootFileDirectory, includeFilename);
                    if (_fileSystem.TryGetFile(testFilename, out text))
                    {
                        return(new SourceFile(text, currentFile, testFilename));
                    }
                }
                fileToCheck = fileToCheck.IncludedBy;
            }

            // Then try additional include directories.
            foreach (var includeDirectory in _parserOptions.AdditionalIncludeDirectories)
            {
                var testFilename = Path.Combine(includeDirectory, includeFilename);
                if (_fileSystem.TryGetFile(testFilename, out text))
                {
                    return(new SourceFile(text, currentFile, testFilename));
                }
            }

            return(null);
        }