docfx
docfx copied to clipboard
[Bug] Custom namespace filter rules not working anymore
Describe the bug I use DocFx to document a specific namespace in my dotnet project.
To achieve my goal I have a filterConfig.yml file where I exclude everything but what I need:
apiRules:
- exclude:
hasAttribute:
uid: Newtonsoft.Json.JsonIgnoreAttribute
- exclude:
uid: .*
type: Method
- exclude:
uid: .*
type: Field
- exclude:
uid: .*
type: Interface
- include:
uidRegex: ^MyApp\.Domain\.Models
- exclude:
uidRegex: ^MyApp\.Domain
But unfortunately, the produced documentation is empty because the last exclude rule is removing everything.
I cloned the source code to attach the debugger and I saw that the class SymbolFilter (method IncludeApi) is correctly validating my rules, but then it checks for the ContainingSymbol as well. And being the Models a child of the Domain namespace, this obviously breaks my rules invalidating the include one.
This didn't happen with the v2.61.0 and according to the documentation this approach shall work.
To Reproduce
Create a dotnet console app MyApp and two classes in two different namespaces:
- MyApp.Domain.Models.Class1
- MyApp.Domain.Class2
Run docfx init --quiet
Fill the metadata property of the docfx.json file as follow:
"metadata": [
{
"src": [
{
"files": [
"**.csproj"
],
"exclude": [
"**/bin/**",
"**/obj/**",
"_site/**",
],
"src": "../"
}
],
"dest": "api",
"filter": "filterConfig.yml",
"includePrivateMembers": false,
"disableGitFeatures": false,
"disableDefaultFilter": false
}
],
And create in the same folder a filterConfig.yml file:
apiRules:
- include:
uidRegex: ^ConsoleApp1\.Domain\.Models
- exclude:
uidRegex: ^ConsoleApp1\.Domain
Run the serve command. Generated documentation will be empty
Expected behavior
Generated documentation shall contain documentation for the ConsoleApp1.Domain.Models namespace (Class1).
To have a test, perform the same steps as above but with the 2.61.0 version installed.
Context:
-
OS: Windows
-
Docfx version: [e.g. 2.62.x]
-
.NET version: NET 6.0
-
docfx.jsonconfig
{
"metadata": [
{
"src": [
{
"files": [
"**/ConsoleApp1.csproj"
],
"exclude": [
"**/bin/**",
"**/obj/**",
"_site/**"
],
"src": "../"
}
],
"dest": "api",
"filter": "filterConfig.yml",
"includePrivateMembers": false,
"disableGitFeatures": false,
"disableDefaultFilter": false
}
],
"build": {
"content": [
{
"files": [
"api/**.yml",
"api/index.md"
]
},
{
"files": [
"articles/**.md",
"articles/**/toc.yml",
"toc.yml",
"*.md"
]
}
],
"resource": [
{
"files": [
"images/**"
]
}
],
"overwrite": [
{
"files": [
"apidoc/**.md"
],
"exclude": [
"obj/**",
"_site/**"
]
}
],
"globalMetadata": {
"_appTitle": "",
"_appFooter": "",
"_gitUrlPattern": "vso",
"_enableNewTab": true,
"_disableContribution": true
},
"dest": "_site",
"globalMetadataFiles": [],
"fileMetadataFiles": [],
"template": [
"default"
],
"postProcessors": [],
"noLangKeyword": false,
"keepFileLink": false,
"disableGitFeatures": false
}
}
apiRules:
- exclude:
hasAttribute:
uid: Newtonsoft.Json.JsonIgnoreAttribute
- exclude:
uid: .*
type: Method
- exclude:
uid: .*
type: Field
- exclude:
uid: .*
type: Interface
- include:
uidRegex: ^ConsoleApp1\.Domain\.Models
- exclude:
uidRegex: ^ConsoleApp1\.Domain
- .NET info
.NET SDK:
Version: 7.0.103
Commit: 276c71d299
Runtime Environment:
OS Name: Windows
OS Version: 10.0.22000
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\7.0.103\
Host:
Version: 7.0.3
Architecture: x64
Commit: 0a2bda10e8
.NET SDKs installed:
3.1.426 [C:\Program Files\dotnet\sdk]
5.0.302 [C:\Program Files\dotnet\sdk]
5.0.403 [C:\Program Files\dotnet\sdk]
5.0.408 [C:\Program Files\dotnet\sdk]
6.0.202 [C:\Program Files\dotnet\sdk]
6.0.203 [C:\Program Files\dotnet\sdk]
6.0.309 [C:\Program Files\dotnet\sdk]
7.0.103 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 3.1.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.21 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.21 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.21 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.8 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.12 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.14 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 7.0.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other architectures found:
arm64 [C:\Program Files\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\arm64\InstallLocation]
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]
Environment variables:
Not set
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
Additional context Add any other context about the problem here.
I think they changed how namespace filters work so one can exclude all child namespaces with a single rule. My guess is that if you change the order of your filter rules and put the rule to include ConsoleApp1.Domain.Models, it should work.
@OscarAbraham thanks for feedback. However, I tried reversing the apiRules as you suggested , but it still doesn't work
apiRules:
- exclude:
uidRegex: ^ConsoleApp1\.Domain
- include:
uidRegex: ^ConsoleApp1\.Domain\.Models
@Krusty93 Sorry. I don't know why I thought it'd work.
@Krusty93 Sorry. I don't know why I thought it'd work.
No problem
In my opinion, this is the line that introduced the bug in PR #8408:
public bool IncludeApi(ISymbol symbol)
{
return IsSymbolAccessible(symbol) && IncludeApiCore(symbol);
bool IncludeApiCore(ISymbol symbol)
{
return _cache.GetOrAdd(symbol, _ => _options.IncludeApi?.Invoke(_) switch
{
SymbolIncludeState.Include => true,
SymbolIncludeState.Exclude => false,
_ => IncludeApiDefault(symbol),
});
}
bool IncludeApiDefault(ISymbol symbol)
{
if (_filterRule is not null && !_filterRule.CanVisitApi(RoslynFilterData.GetSymbolFilterData(symbol)))
return false;
return symbol.ContainingSymbol is null || IncludeApiCore(symbol.ContainingSymbol);
}
}
CanVisitApi returns true because the apiRules has an include rule on the ConsoleApp1.Domain.Models folder; however, the method is called again recursively passing the ContainingSymbol as argumen that has the value of ConsoleApp1.Domain. This value is not accepted, so it returns false. For this reason, the flow ends up excluding the "more specific" namespace, being in contrast with what the documentation says.
I'm encountering the same problem, the include doesn't seem to work at all.
I just ran into the same issue with DocFx V2.71.0 My use case is that I only want to document things in a specific Namespace. In order to do so I have to 1st exclude everything, and then include the namespace I want (at least I understand the documentation like that). This is what I came up with:
apiRules:
- include:
uidRegex: ^Company\.Product\.Component\.
#type: Namespace
- exclude:
uidRegex: .*
#type: Namespace
I tried it with the type: Namespace and without, I changed the order, ...
But I get everything unfiltered (I I reverse the order), or I get nothing with the warning: No .NET API detected for...
This issue is expected to be fixed in latest version of docfx. (By #9666)