private SyntaxTree?TryGetSyntaxTree(string fullFileName, out DiagnosticBuilder.ErrorBuilderDelegate?failureBuilder)
        {
            var normalizedFileName = fileResolver.GetNormalizedFileName(fullFileName);

            if (syntaxTrees.TryGetValue(normalizedFileName, out var syntaxTree))
            {
                failureBuilder = null;
                return(syntaxTree);
            }

            if (syntaxTreeLoadFailures.TryGetValue(normalizedFileName, out failureBuilder))
            {
                return(null);
            }

            var fileContents = fileResolver.TryRead(normalizedFileName, out var failureMessage);

            if (fileContents == null)
            {
                // TODO: If we upgrade to netstandard2.1, we should be able to use the following to hint to the compiler that failureBuilder is non-null:
                // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/nullable-analysis
                var concreteFailureMessage = failureMessage ?? throw new InvalidOperationException($"Expected {nameof(fileResolver.TryRead)} to provide failure diagnostics");

                failureBuilder = x => x.ErrorOccurredLoadingModule(concreteFailureMessage);
                syntaxTreeLoadFailures[normalizedFileName] = failureBuilder;
                return(null);
            }

            failureBuilder = null;
            return(AddSyntaxTree(normalizedFileName, fileContents));
        }
        public static SyntaxTreeGrouping Build(IFileResolver fileResolver, string entryFileName)
        {
            var builder            = new SyntaxTreeGroupingBuilder(fileResolver);
            var normalizedFileName = fileResolver.GetNormalizedFileName(entryFileName);

            return(builder.Build(normalizedFileName));
        }
        public static SyntaxTreeGrouping BuildWithPreloadedFile(IFileResolver fileResolver, string entryFileName, string fileContents)
        {
            var builder            = new SyntaxTreeGroupingBuilder(fileResolver);
            var normalizedFileName = fileResolver.GetNormalizedFileName(entryFileName);

            builder.AddSyntaxTree(normalizedFileName, fileContents);

            return(builder.Build(normalizedFileName));
        }