Skip to content

Commit f16d314

Browse files
authored
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 <yufeih@users.noreply.github.com>
1 parent ef5eeb0 commit f16d314

File tree

136 files changed

+4123
-1358
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

136 files changed

+4123
-1358
lines changed

docs/reference/docfx-json-reference.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -297,19 +297,26 @@ Specifies the source projects using [File Mappings](#file-mappings).
297297

298298
### `output`
299299

300-
Defines the output folder of the generated metadata files relative to `docfx.json` directory. The `docfx metadata --output <outdir>` command line argument overrides this value.
300+
Specifies the output folder of the generated metadata files relative to `docfx.json` directory. The `docfx metadata --output <outdir>` command line argument overrides this value.
301+
302+
### `outputFormat`
303+
304+
Specifies the generated output file format.
305+
306+
- `mref` (default): output as ManagedReference YAML files.
307+
- `markdown`: Output as common-mark compliant markdown file.
301308

302309
### `dest`
303310

304-
Defines the output folder of the generated metadata files relative to `docfx.json` directory. The `docfx metadata --output <outdir>` command line argument prepends this value.
311+
Specifies the output folder of the generated metadata files relative to `docfx.json` directory. The `docfx metadata --output <outdir>` command line argument prepends this value.
305312

306313
### `shouldSkipMarkup`
307314

308315
If set to true, DocFX would not render triple-slash-comments in source code as markdown.
309316

310317
### `filter`
311318

312-
Defines the filter configuration file, please go to [How to filter out unwanted apis attributes](../tutorial/howto_filter_out_unwanted_apis_attributes.md) for more details.
319+
Specifies the filter configuration file, please go to [How to filter out unwanted apis attributes](../tutorial/howto_filter_out_unwanted_apis_attributes.md) for more details.
313320

314321
### `disableDefaultFilter`
315322

@@ -321,7 +328,7 @@ Disables generation of view source links.
321328

322329
### `properties`
323330

324-
Defines an optional set of MSBuild properties used when interpreting project files. These are the same properties that are passed to msbuild via the `/property:name=value` command line argument.
331+
Specifies an optional set of MSBuild properties used when interpreting project files. These are the same properties that are passed to msbuild via the `/property:name=value` command line argument.
325332

326333
```json
327334
{
@@ -343,14 +350,14 @@ Do not run `dotnet restore` before building the projects.
343350

344351
### `namespaceLayout`
345352

346-
Defines how namespaces in TOC are organized:
353+
Specifies how namespaces in TOC are organized:
347354

348355
- `flattened` (default): Renders namespaces as a single flat list.
349356
- `nested`: Renders namespaces in a nested tree form.
350357

351358
### `memberLayout`
352359

353-
Defines how member pages are organized:
360+
Specifies how member pages are organized:
354361

355362
- `samePage` (default): Places members in the same page as their containing type.
356363
- `separatePages`: Places members in separate pages.
@@ -361,7 +368,7 @@ When enabled, continues documentation generation in case of compilation errors.
361368

362369
### `EnumSortOrder`
363370

364-
Defines how enum members are sorted:
371+
Specifies how enum members are sorted:
365372

366373
- `alphabetic` (default): Sort enum members in alphabetic order.
367374
- `declaringOrder`: Sort enum members in the order as they are declared in the source code.
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Diagnostics;
5+
using Docfx.Common;
6+
using Microsoft.Build.Construction;
7+
using Microsoft.Build.Framework;
8+
using Microsoft.Build.Logging;
9+
using Microsoft.CodeAnalysis;
10+
using Microsoft.CodeAnalysis.MSBuild;
11+
12+
#nullable enable
13+
14+
namespace Docfx.Dotnet;
15+
16+
partial class DotnetApiCatalog
17+
{
18+
private static async Task<List<(IAssemblySymbol symbol, Compilation compilation)>> Compile(ExtractMetadataConfig config, DotnetApiOptions options)
19+
{
20+
var files = config.Files?.Select(s => new FileInformation(s))
21+
.GroupBy(f => f.Type)
22+
.ToDictionary(s => s.Key, s => s.Distinct().ToList()) ?? new();
23+
24+
var msbuildProperties = config.MSBuildProperties ?? new Dictionary<string, string>();
25+
if (!msbuildProperties.ContainsKey("Configuration"))
26+
{
27+
msbuildProperties["Configuration"] = "Release";
28+
}
29+
30+
var msbuildLogger = new ConsoleLogger(Logger.LogLevelThreshold switch
31+
{
32+
LogLevel.Verbose => LoggerVerbosity.Normal,
33+
LogLevel.Diagnostic => LoggerVerbosity.Diagnostic,
34+
_ => LoggerVerbosity.Quiet,
35+
});
36+
37+
var workspace = MSBuildWorkspace.Create(msbuildProperties);
38+
workspace.WorkspaceFailed += (sender, e) => Logger.LogWarning($"{e.Diagnostic}");
39+
40+
if (files.TryGetValue(FileType.NotSupported, out var unsupportedFiles))
41+
{
42+
foreach (var file in unsupportedFiles)
43+
{
44+
Logger.LogWarning($"Skip unsupported file {file}");
45+
}
46+
}
47+
48+
var hasCompilationError = false;
49+
var projectCompilations = new HashSet<Compilation>();
50+
var assemblies = new List<(IAssemblySymbol, Compilation)>();
51+
52+
if (files.TryGetValue(FileType.Solution, out var solutionFiles))
53+
{
54+
foreach (var solution in solutionFiles.Select(s => s.NormalizedPath))
55+
{
56+
Logger.LogInfo($"Loading solution {solution}");
57+
foreach (var project in SolutionFile.Parse(solution).ProjectsInOrder)
58+
{
59+
if (project.ProjectType is SolutionProjectType.KnownToBeMSBuildFormat &&
60+
await LoadCompilationFromProject(project.AbsolutePath) is { } compilation)
61+
{
62+
projectCompilations.Add(compilation);
63+
}
64+
}
65+
}
66+
}
67+
68+
if (files.TryGetValue(FileType.Project, out var projectFiles))
69+
{
70+
foreach (var projectFile in projectFiles)
71+
{
72+
if (await LoadCompilationFromProject(projectFile.NormalizedPath) is { } compilation)
73+
{
74+
projectCompilations.Add(compilation);
75+
}
76+
}
77+
}
78+
79+
foreach (var compilation in projectCompilations)
80+
{
81+
hasCompilationError |= compilation.CheckDiagnostics(config.AllowCompilationErrors);
82+
assemblies.Add((compilation.Assembly, compilation));
83+
}
84+
85+
if (files.TryGetValue(FileType.CSSourceCode, out var csFiles))
86+
{
87+
var compilation = CompilationHelper.CreateCompilationFromCSharpFiles(csFiles.Select(f => f.NormalizedPath));
88+
hasCompilationError |= compilation.CheckDiagnostics(config.AllowCompilationErrors);
89+
assemblies.Add((compilation.Assembly, compilation));
90+
}
91+
92+
if (files.TryGetValue(FileType.VBSourceCode, out var vbFiles))
93+
{
94+
var compilation = CompilationHelper.CreateCompilationFromVBFiles(vbFiles.Select(f => f.NormalizedPath));
95+
hasCompilationError |= compilation.CheckDiagnostics(config.AllowCompilationErrors);
96+
assemblies.Add((compilation.Assembly, compilation));
97+
}
98+
99+
if (files.TryGetValue(FileType.Assembly, out var assemblyFiles))
100+
{
101+
foreach (var assemblyFile in assemblyFiles)
102+
{
103+
Logger.LogInfo($"Loading assembly {assemblyFile.NormalizedPath}");
104+
var (compilation, assembly) = CompilationHelper.CreateCompilationFromAssembly(assemblyFile.NormalizedPath, config.References);
105+
hasCompilationError |= compilation.CheckDiagnostics(config.AllowCompilationErrors);
106+
assemblies.Add((assembly, compilation));
107+
}
108+
}
109+
110+
if (hasCompilationError)
111+
{
112+
return new();
113+
}
114+
115+
if (assemblies.Count <= 0)
116+
{
117+
Logger.LogWarning("No .NET API project detected.");
118+
}
119+
120+
return assemblies;
121+
122+
async Task<Compilation?> LoadCompilationFromProject(string path)
123+
{
124+
var project = workspace.CurrentSolution.Projects.FirstOrDefault(
125+
p => FilePathComparer.OSPlatformSensitiveRelativePathComparer.Equals(p.FilePath, path));
126+
127+
if (project is null)
128+
{
129+
Logger.LogInfo($"Loading project {path}");
130+
if (!config.NoRestore)
131+
{
132+
await Process.Start("dotnet", $"restore \"{path}\"").WaitForExitAsync();
133+
}
134+
project = await workspace.OpenProjectAsync(path, msbuildLogger);
135+
}
136+
137+
if (!project.SupportsCompilation)
138+
{
139+
Logger.LogInfo($"Skip unsupported project {project.FilePath}.");
140+
return null;
141+
}
142+
143+
return await project.GetCompilationAsync();
144+
}
145+
}
146+
}

0 commit comments

Comments
 (0)