diff --git a/src/Docfx.Dotnet/Filters/ConfigFilterRuleItemUnion.cs b/src/Docfx.Dotnet/Filters/ConfigFilterRuleItemUnion.cs index a802bb5be77..028750cdb85 100644 --- a/src/Docfx.Dotnet/Filters/ConfigFilterRuleItemUnion.cs +++ b/src/Docfx.Dotnet/Filters/ConfigFilterRuleItemUnion.cs @@ -52,6 +52,10 @@ public ConfigFilterRuleItem Rule { return Include; } + + // If kind is not specified for exclude. Set `ExtendedSymbolKind.Type` as default kind. + Exclude.Kind ??= ExtendedSymbolKind.Type | ExtendedSymbolKind.Member; + return Exclude; } } diff --git a/src/Docfx.Dotnet/Filters/ExtendedSymbolKind.cs b/src/Docfx.Dotnet/Filters/ExtendedSymbolKind.cs index a8502c78cc6..0fcd1a7f0ab 100644 --- a/src/Docfx.Dotnet/Filters/ExtendedSymbolKind.cs +++ b/src/Docfx.Dotnet/Filters/ExtendedSymbolKind.cs @@ -3,23 +3,30 @@ namespace Docfx.Dotnet; +[Flags] internal enum ExtendedSymbolKind { - Assembly = 0x100, - Namespace = 0x110, - Type = 0x120, - Class, - Struct, - Enum, - Interface, - Delegate, - Member = 0x200, - Event, - Field, - Method, - Property, +#pragma warning disable format + Assembly = 1 << 1, + Namespace = 1 << 2, + // Type + Class = 1 << 3, + Struct = 1 << 4, + Enum = 1 << 5, + Interface = 1 << 6, + Delegate = 1 << 7, + // Member + Event = 1 << 8, + Field = 1 << 9, + Method = 1 << 10, + Property = 1 << 11, +#pragma warning restore format + + Type = Class | Struct | Enum | Interface | Delegate, + Member = Event | Field | Method | Property, } + internal static class ExtendedSymbolKindHelper { public static bool Contains(this ExtendedSymbolKind kind, SymbolFilterData symbol) @@ -30,6 +37,6 @@ public static bool Contains(this ExtendedSymbolKind kind, SymbolFilterData symbo { return false; } - return (kind & k.Value) == kind; + return (kind & k.Value) > 0; } } diff --git a/test/Docfx.Dotnet.Tests/ApiFilterUnitTest.cs b/test/Docfx.Dotnet.Tests/ApiFilterUnitTest.cs index eeb337aebed..d2b154fda59 100644 --- a/test/Docfx.Dotnet.Tests/ApiFilterUnitTest.cs +++ b/test/Docfx.Dotnet.Tests/ApiFilterUnitTest.cs @@ -327,6 +327,44 @@ public interface IClass1 Assert.Empty(class1.Items); } + [Fact] + public void TestDocsSampleFilter() + { + var code = @" +namespace Microsoft.DevDiv +{ + public class Class1 + { + } +} +namespace Microsoft.DevDiv.SpecialCase +{ + public class NestedClass : Class1 + { + } +} +"; + string configFile = "TestData/filterconfig_docs_sample.yml"; + MetadataItem output = Verify(code, new() { FilterConfigFile = configFile }); + + var namespaces = output.Items; + Assert.Single(namespaces); + + var @namespace = namespaces[0]; + Assert.NotNull(@namespace); + Assert.Equal("Microsoft.DevDiv.SpecialCase", @namespace.Name); + Assert.Single(@namespace.Items); + + var nestedClass = @namespace.Items[0]; + Assert.Equal("Microsoft.DevDiv.SpecialCase.NestedClass", nestedClass.Name); + } + + [Fact] + public void TestExtendedSymbolKindFlags() + { + Assert.True((ExtendedSymbolKind.Type | ExtendedSymbolKind.Member).Contains(new SymbolFilterData { Kind = ExtendedSymbolKind.Interface })); + } + private static MetadataItem Verify(string code, ExtractMetadataConfig config = null, DotnetApiOptions options = null) { var compilation = CompilationHelper.CreateCompilationFromCSharpCode(code, "test.dll"); diff --git a/test/Docfx.Dotnet.Tests/TestData/filterconfig_docs_sample.yml b/test/Docfx.Dotnet.Tests/TestData/filterconfig_docs_sample.yml new file mode 100644 index 00000000000..4aca7206ff7 --- /dev/null +++ b/test/Docfx.Dotnet.Tests/TestData/filterconfig_docs_sample.yml @@ -0,0 +1,5 @@ +apiRules: +- include: + uidRegex: ^Microsoft\.DevDiv\.SpecialCase +- exclude: + uidRegex: ^Microsoft\.DevDiv