Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Custom namespace filter rules not working anymore #8427

Open
Krusty93 opened this issue Feb 20, 2023 · 7 comments
Open

[Bug] Custom namespace filter rules not working anymore #8427

Krusty93 opened this issue Feb 20, 2023 · 7 comments
Labels
bug A bug to fix dotnet Generate .NET API reference docs

Comments

@Krusty93
Copy link

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:

  1. MyApp.Domain.Models.Class1
  2. 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.json config

{
  "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.

@Krusty93 Krusty93 added bug A bug to fix dotnet Generate .NET API reference docs labels Feb 20, 2023
@OscarAbraham
Copy link

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.

@Krusty93
Copy link
Author

@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

@OscarAbraham
Copy link

@Krusty93 Sorry. I don't know why I thought it'd work.

@Krusty93
Copy link
Author

Krusty93 commented Feb 26, 2023

@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.

@Lagann311
Copy link

I'm encountering the same problem, the include doesn't seem to work at all.

@osre77
Copy link

osre77 commented Nov 2, 2023

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...

@filzrev
Copy link
Contributor

filzrev commented Apr 29, 2024

This issue is expected to be fixed in latest version of docfx. (By #9666)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A bug to fix dotnet Generate .NET API reference docs
Projects
None yet
Development

No branches or pull requests

5 participants