-
Notifications
You must be signed in to change notification settings - Fork 867
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: re-organize dotnet reference generation (#9258)
* wip * refactor: re-organize dotnet reference generation * test(snapshot): update snapshots for 797dcac * Add back md snapshots * minor adjustments * test(snapshot): update snapshots for d862373 * markdown escape * fix tests * test(snapshot): update snapshots for 2383aaa * adjust docs * update escape chars * test(snapshot): update snapshots for 67d13fb --------- Co-authored-by: Yufei Huang <[email protected]>
- Loading branch information
Showing
136 changed files
with
4,123 additions
and
1,358 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Diagnostics; | ||
using Docfx.Common; | ||
using Microsoft.Build.Construction; | ||
using Microsoft.Build.Framework; | ||
using Microsoft.Build.Logging; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.MSBuild; | ||
|
||
#nullable enable | ||
|
||
namespace Docfx.Dotnet; | ||
|
||
partial class DotnetApiCatalog | ||
{ | ||
private static async Task<List<(IAssemblySymbol symbol, Compilation compilation)>> Compile(ExtractMetadataConfig config, DotnetApiOptions options) | ||
{ | ||
var files = config.Files?.Select(s => new FileInformation(s)) | ||
.GroupBy(f => f.Type) | ||
.ToDictionary(s => s.Key, s => s.Distinct().ToList()) ?? new(); | ||
|
||
var msbuildProperties = config.MSBuildProperties ?? new Dictionary<string, string>(); | ||
if (!msbuildProperties.ContainsKey("Configuration")) | ||
{ | ||
msbuildProperties["Configuration"] = "Release"; | ||
} | ||
|
||
var msbuildLogger = new ConsoleLogger(Logger.LogLevelThreshold switch | ||
{ | ||
LogLevel.Verbose => LoggerVerbosity.Normal, | ||
LogLevel.Diagnostic => LoggerVerbosity.Diagnostic, | ||
_ => LoggerVerbosity.Quiet, | ||
}); | ||
|
||
var workspace = MSBuildWorkspace.Create(msbuildProperties); | ||
workspace.WorkspaceFailed += (sender, e) => Logger.LogWarning($"{e.Diagnostic}"); | ||
|
||
if (files.TryGetValue(FileType.NotSupported, out var unsupportedFiles)) | ||
{ | ||
foreach (var file in unsupportedFiles) | ||
{ | ||
Logger.LogWarning($"Skip unsupported file {file}"); | ||
} | ||
} | ||
|
||
var hasCompilationError = false; | ||
var projectCompilations = new HashSet<Compilation>(); | ||
var assemblies = new List<(IAssemblySymbol, Compilation)>(); | ||
|
||
if (files.TryGetValue(FileType.Solution, out var solutionFiles)) | ||
{ | ||
foreach (var solution in solutionFiles.Select(s => s.NormalizedPath)) | ||
{ | ||
Logger.LogInfo($"Loading solution {solution}"); | ||
foreach (var project in SolutionFile.Parse(solution).ProjectsInOrder) | ||
{ | ||
if (project.ProjectType is SolutionProjectType.KnownToBeMSBuildFormat && | ||
await LoadCompilationFromProject(project.AbsolutePath) is { } compilation) | ||
{ | ||
projectCompilations.Add(compilation); | ||
} | ||
} | ||
} | ||
} | ||
|
||
if (files.TryGetValue(FileType.Project, out var projectFiles)) | ||
{ | ||
foreach (var projectFile in projectFiles) | ||
{ | ||
if (await LoadCompilationFromProject(projectFile.NormalizedPath) is { } compilation) | ||
{ | ||
projectCompilations.Add(compilation); | ||
} | ||
} | ||
} | ||
|
||
foreach (var compilation in projectCompilations) | ||
{ | ||
hasCompilationError |= compilation.CheckDiagnostics(config.AllowCompilationErrors); | ||
assemblies.Add((compilation.Assembly, compilation)); | ||
} | ||
|
||
if (files.TryGetValue(FileType.CSSourceCode, out var csFiles)) | ||
{ | ||
var compilation = CompilationHelper.CreateCompilationFromCSharpFiles(csFiles.Select(f => f.NormalizedPath)); | ||
hasCompilationError |= compilation.CheckDiagnostics(config.AllowCompilationErrors); | ||
assemblies.Add((compilation.Assembly, compilation)); | ||
} | ||
|
||
if (files.TryGetValue(FileType.VBSourceCode, out var vbFiles)) | ||
{ | ||
var compilation = CompilationHelper.CreateCompilationFromVBFiles(vbFiles.Select(f => f.NormalizedPath)); | ||
hasCompilationError |= compilation.CheckDiagnostics(config.AllowCompilationErrors); | ||
assemblies.Add((compilation.Assembly, compilation)); | ||
} | ||
|
||
if (files.TryGetValue(FileType.Assembly, out var assemblyFiles)) | ||
{ | ||
foreach (var assemblyFile in assemblyFiles) | ||
{ | ||
Logger.LogInfo($"Loading assembly {assemblyFile.NormalizedPath}"); | ||
var (compilation, assembly) = CompilationHelper.CreateCompilationFromAssembly(assemblyFile.NormalizedPath, config.References); | ||
hasCompilationError |= compilation.CheckDiagnostics(config.AllowCompilationErrors); | ||
assemblies.Add((assembly, compilation)); | ||
} | ||
} | ||
|
||
if (hasCompilationError) | ||
{ | ||
return new(); | ||
} | ||
|
||
if (assemblies.Count <= 0) | ||
{ | ||
Logger.LogWarning("No .NET API project detected."); | ||
} | ||
|
||
return assemblies; | ||
|
||
async Task<Compilation?> LoadCompilationFromProject(string path) | ||
{ | ||
var project = workspace.CurrentSolution.Projects.FirstOrDefault( | ||
p => FilePathComparer.OSPlatformSensitiveRelativePathComparer.Equals(p.FilePath, path)); | ||
|
||
if (project is null) | ||
{ | ||
Logger.LogInfo($"Loading project {path}"); | ||
if (!config.NoRestore) | ||
{ | ||
await Process.Start("dotnet", $"restore \"{path}\"").WaitForExitAsync(); | ||
} | ||
project = await workspace.OpenProjectAsync(path, msbuildLogger); | ||
} | ||
|
||
if (!project.SupportsCompilation) | ||
{ | ||
Logger.LogInfo($"Skip unsupported project {project.FilePath}."); | ||
return null; | ||
} | ||
|
||
return await project.GetCompilationAsync(); | ||
} | ||
} | ||
} |
Oops, something went wrong.