private static List <string> MergeFixedCode(IReadOnlyList <string> codes, string fixedCode)
        {
            var merged     = new List <string>(codes.Count);
            var found      = false;
            var @namespace = CodeReader.Namespace(fixedCode);
            var fileName   = CodeReader.FileName(fixedCode);

            foreach (var code in codes)
            {
                if (CodeReader.FileName(code) == fileName &&
                    CodeReader.Namespace(code) == @namespace)
                {
                    if (found)
                    {
                        throw new AssertException("Expected unique class names.");
                    }

                    merged.Add(fixedCode);
                    found = true;
                }
                else
                {
                    merged.Add(code);
                }
            }

            if (!found)
            {
                throw new AssertException("Failed merging expected one class to have same namespace and class name as fixedCode.\r\n" +
                                          "Try specifying a list with all fixed code.");
            }

            return(merged);
        }
        /// <summary>
        /// Create a <see cref="Solution"/> for <paramref name="code"/>
        /// Each unique namespace in <paramref name="code"/> is added as a project.
        /// </summary>
        /// <param name="code">The code to create the solution from.</param>
        /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/>.</param>
        /// <param name="metadataReferences">The metadata references.</param>
        /// <returns>A <see cref="Solution"/>.</returns>
        public static Solution CreateSolutionWithOneProject(IEnumerable <string> code, CSharpCompilationOptions compilationOptions, IEnumerable <MetadataReference> metadataReferences = null)
        {
            var projectInfo = GetProjectInfo();

            return(EmptySolution.AddProject(projectInfo));

            ProjectInfo GetProjectInfo()
            {
                string projectName = null;

                foreach (var doc in code)
                {
                    if (projectName == null)
                    {
                        projectName = CodeReader.Namespace(doc);
                    }
                    else
                    {
                        var ns      = CodeReader.Namespace(doc);
                        var indexOf = ns.IndexOf('.');
                        if (indexOf > 0)
                        {
                            ns = ns.Substring(0, indexOf);
                        }

                        if (ns.Length < projectName.Length)
                        {
                            projectName = ns;
                        }
                    }
                }

                var projectId = ProjectId.CreateNewId(projectName);

                return(ProjectInfo.Create(
                           projectId,
                           VersionStamp.Default,
                           projectName,
                           projectName,
                           LanguageNames.CSharp,
                           metadataReferences: metadataReferences,
                           compilationOptions: compilationOptions,
                           documents: code.Select(
                               x =>
                {
                    var documentName = CodeReader.FileName(x);
                    return DocumentInfo.Create(
                        DocumentId.CreateNewId(projectId, documentName),
                        documentName,
                        sourceCodeKind: SourceCodeKind.Regular,
                        loader: TextLoader.From(
                            TextAndVersion.Create(
                                SourceText.From(x, (Encoding)null, SourceHashAlgorithm.Sha1),
                                VersionStamp.Default)));
                })));
            }
        }
Example #3
0
        private static async Task AreEqualAsync(IReadOnlyList <string> expected, Solution actual, string?messageHeader)
        {
            var actualCount = actual.Projects.SelectMany(x => x.Documents).Count();

            if (expected.Count != actualCount)
            {
                throw new AssertException($"Expected {expected.Count} documents the fixed solution has {actualCount} documents.");
            }

            foreach (var project in actual.Projects)
            {
                foreach (var document in project.Documents)
                {
                    var fixedSource = await CodeReader.GetStringFromDocumentAsync(document, CancellationToken.None).ConfigureAwait(false);

                    CodeAssert.AreEqual(FindExpected(fixedSource), fixedSource, messageHeader);
                }
            }

            string FindExpected(string fixedSource)
            {
                var fixedNamespace = CodeReader.Namespace(fixedSource);
                var fixedFileName  = CodeReader.FileName(fixedSource);
                var match          = expected.FirstOrDefault(x => x == fixedSource);

                if (match != null)
                {
                    return(match);
                }

                foreach (var candidate in expected)
                {
                    if (CodeReader.Namespace(candidate) == fixedNamespace &&
                        CodeReader.FileName(candidate) == fixedFileName)
                    {
                        return(candidate);
                    }
                }

                throw new AssertException($"The fixed solution contains a document {fixedFileName} in namespace {fixedNamespace} that is not in the expected documents.");
            }
        }
Example #4
0
 public SourceMetadata(string code)
 {
     this.Code      = code;
     this.FileName  = CodeReader.FileName(code);
     this.Namespace = CodeReader.Namespace(code);
 }
        /// <summary>
        /// Create a <see cref="Solution"/> for <paramref name="code"/>
        /// Each unique namespace in <paramref name="code"/> is added as a project.
        /// </summary>
        /// <param name="code">The code to create the solution from.</param>
        /// <param name="compilationOptions">The <see cref="CSharpCompilationOptions"/>.</param>
        /// <param name="metadataReferences">The metadata references.</param>
        /// <param name="languageVersion">The <see cref="LanguageVersion"/>.</param>
        /// <returns>A <see cref="Solution"/>.</returns>
        public static Solution CreateSolution(IEnumerable <string> code, CSharpCompilationOptions compilationOptions, IEnumerable <MetadataReference> metadataReferences = null, LanguageVersion languageVersion = LanguageVersion.Latest)
        {
            var solutionInfo = SolutionInfo.Create(
                SolutionId.CreateNewId("Test.sln"),
                VersionStamp.Default,
                projects: GetProjectInfos());
            var solution = EmptySolution;

            foreach (var projectInfo in solutionInfo.Projects)
            {
                solution = solution.AddProject(projectInfo.WithProjectReferences(FindReferences(projectInfo)));
            }

            return(solution);

            IEnumerable <ProjectInfo> GetProjectInfos()
            {
                var byNamespace = new SortedDictionary <string, List <string> >();

                foreach (var document in code)
                {
                    var ns = CodeReader.Namespace(document);
                    if (byNamespace.TryGetValue(ns, out var doc))
                    {
                        doc.Add(document);
                    }
                    else
                    {
                        byNamespace[ns] = new List <string> {
                            document
                        };
                    }
                }

                var byProject = new SortedDictionary <string, List <KeyValuePair <string, List <string> > > >();

                foreach (var kvp in byNamespace)
                {
                    var last = byProject.Keys.LastOrDefault();
                    var ns   = kvp.Key;
                    if (last != null &&
                        ns.Contains(last))
                    {
                        byProject[last].Add(kvp);
                    }
                    else
                    {
                        byProject.Add(ns, new List <KeyValuePair <string, List <string> > > {
                            kvp
                        });
                    }
                }

                foreach (var kvp in byProject)
                {
                    var assemblyName = kvp.Key;
                    var projectId    = ProjectId.CreateNewId(assemblyName);
                    yield return(ProjectInfo.Create(
                                     projectId,
                                     VersionStamp.Default,
                                     assemblyName,
                                     assemblyName,
                                     LanguageNames.CSharp,
                                     compilationOptions: compilationOptions,
                                     metadataReferences: metadataReferences,
                                     documents: kvp.Value.SelectMany(x => x.Value)
                                     .Select(
                                         x =>
                    {
                        var documentName = CodeReader.FileName(x);
                        return DocumentInfo.Create(
                            DocumentId.CreateNewId(projectId, documentName),
                            documentName,
                            sourceCodeKind: SourceCodeKind.Regular,
                            loader: new StringLoader(x));
                    }))
                                 .WithParseOptions(CSharpParseOptions.Default.WithLanguageVersion(languageVersion)));
                }
            }

            IEnumerable <ProjectReference> FindReferences(ProjectInfo projectInfo)
            {
                var references = new List <ProjectReference>();

                foreach (var other in solutionInfo.Projects.Where(x => x.Id != projectInfo.Id))
                {
                    if (projectInfo.Documents.Any(x => x.TextLoader is StringLoader stringLoader &&
                                                  (stringLoader.Code.Contains($"using {other.Name};") ||
                                                   stringLoader.Code.Contains($"{other.Name}."))))
                    {
                        references.Add(new ProjectReference(other.Id));
                    }
                }

                return(references);
            }
        }