Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ public DocIdExcludeListFilter(string excludeListFilePath, bool excludeMembers)
_excludeMembers = excludeMembers;
}

public bool IncludeForwardedTypes { get; set; }

public bool Include(INamespaceDefinition ns)
{
// Only include non-empty namespaces
if (!ns.GetTypes().Any(Include))
if (!ns.GetTypes(IncludeForwardedTypes).Any(Include))
return false;

string namespaceId = ns.DocId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ public DocIdIncludeListFilter(string includeListFilePath)

public bool AlwaysIncludeNonEmptyTypes { get; set; }

public bool IncludeForwardedTypes { get; set; }

public bool Include(INamespaceDefinition ns)
{
// Only include non-empty namespaces
if (!ns.GetTypes().Any(Include))
if (!ns.GetTypes(IncludeForwardedTypes).Any(Include))
return false;

string namespaceId = ns.DocId();
Expand Down
58 changes: 56 additions & 2 deletions src/Microsoft.Cci.Extensions/Writers/CSharp/CSharpWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class CSharpWriter : SimpleTypeMemberTraverser, ICciWriter, IDisposable
private readonly bool _apiOnly;
private readonly ICciFilter _cciFilter;
private bool _firstMemberGroup;
private ICciFilter _currentTypeListFilter;

public CSharpWriter(ISyntaxWriter writer, ICciFilter filter, bool apiOnly, bool writeAssemblyAttributes = false)
: base(filter)
Expand All @@ -34,6 +35,12 @@ public CSharpWriter(ISyntaxWriter writer, ICciFilter filter, bool apiOnly, bool
_writeAssemblyAttributes = writeAssemblyAttributes;
}

public class ConditionalTypeList
{
public ICciFilter Filter { get; set; }
public string Symbol { get; set; }
}

public ISyntaxWriter SyntaxWriter { get { return _syntaxWriter; } }

public ICciDeclarationWriter DeclarationWriter { get { return _declarationWriter; } }
Expand All @@ -48,6 +55,10 @@ public CSharpWriter(ISyntaxWriter writer, ICciFilter filter, bool apiOnly, bool

public bool PutBraceOnNewLine { get; set; }

public IEnumerable<ConditionalTypeList> ConditionalTypeLists { get; set; }

public string DefaultCondition { get; set; }

public bool IncludeGlobalPrefixForCompilation
{
get { return _declarationWriter.ForCompilationIncludeGlobalPrefix; }
Expand Down Expand Up @@ -87,7 +98,23 @@ public override void Visit(IAssembly assembly)
_declarationWriter.WriteDeclaration(assembly);
}

base.Visit(assembly);
var namespaces = assembly.GetAllNamespaces();
_currentTypeListFilter = null;

// first pass, visit types *not* mentioned in ConditionalTypeLists
WriteConditionStart(DefaultCondition);
Visit(namespaces);
WriteConditionEnd(DefaultCondition);

// second pass, visit types mentioned in ConditionalTypeLists
foreach (var typeList in ConditionalTypeLists ?? Enumerable.Empty<ConditionalTypeList>())
{
_currentTypeListFilter = typeList.Filter;

WriteConditionStart(typeList.Symbol);
Visit(namespaces.Where(_currentTypeListFilter.Include));
WriteConditionEnd(typeList.Symbol);
}
}

public override void Visit(INamespaceDefinition ns)
Expand All @@ -102,7 +129,16 @@ public override void Visit(INamespaceDefinition ns)

using (_syntaxWriter.StartBraceBlock(PutBraceOnNewLine))
{
base.Visit(ns);
var types = ns.GetTypes(this.IncludeForwardedTypes);
if (ConditionalTypeLists != null)
{
// in the first pass we want all types *except* the ones in ConditionalTypeLists filters
// in the second pass we want *only* the types in ConditionalTypeLists filters
var firstPass = _currentTypeListFilter == null;
types = types.Where(t => ConditionalTypeLists.Any(c => c.Filter.Include(t) == !firstPass));
}

Visit(types);
}
}

Expand Down Expand Up @@ -296,6 +332,24 @@ private void WriteMemberGroupHeader(ITypeDefinitionMember member)
}
}

private void WriteConditionStart(string condition)
{
if (!string.IsNullOrEmpty(condition))
{
_syntaxWriter.Write($"#if {condition}");
_syntaxWriter.WriteLine();
}
}

private void WriteConditionEnd(string condition)
{
if (!string.IsNullOrEmpty(condition))
{
_syntaxWriter.Write($"#endif // {condition}");
_syntaxWriter.WriteLine();
}
}

public static string MemberGroupHeading(ITypeDefinitionMember member)
{
if (member == null)
Expand Down
25 changes: 23 additions & 2 deletions src/Microsoft.DotNet.GenAPI/GenAPITask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,24 @@ public string DocIdKinds
/// </summary>
public bool AlwaysIncludeBase { get; set; }

/// <summary>
/// [CSDecl] Specify one or more namespace+type list(s) in the DocId format of types that should be wrapped inside an #if with the symbol specified in the <c>Symbol</c> metadata item.
/// If the <c>Symbol</c> metadata item is empty the types won't be wrapped but will still be output after all other types, this can be used in combination with <see cref="DefaultCondition" /> to wrap all other types.
/// </summary>
public ITaskItem[] ConditionalTypeLists { get; set; }

/// <summary>
/// [CSDecl] #if condition to apply to all types not included in <see cref="ConditionalTypeLists" />.
/// </summary>
public string DefaultCondition { get; set; }

/// <summary>
/// Exclude members when return value or parameter types are excluded.
/// </summary>
public bool ExcludeMembers { get; set; }

/// <summary>
/// Language Version to target.
/// [CSDecl] Language Version to target.
/// </summary>
public string LangVersion { get; set; }

Expand Down Expand Up @@ -333,7 +344,7 @@ private static ICciFilter GetFilter(

if (!string.IsNullOrWhiteSpace(excludeApiList))
{
includeFilter = new IntersectionFilter(includeFilter, new DocIdExcludeListFilter(excludeApiList, excludeMembers));
includeFilter = new IntersectionFilter(includeFilter, new DocIdExcludeListFilter(excludeApiList, excludeMembers) { IncludeForwardedTypes = includeForwardedTypes });
}

if (!string.IsNullOrWhiteSpace(excludeAttributesList))
Expand Down Expand Up @@ -394,6 +405,16 @@ private ICciWriter GetWriter(TextWriter output, ISyntaxWriter syntaxWriter, bool
writer.AlwaysIncludeBase = AlwaysIncludeBase;
writer.LangVersion = GetLangVersion(LangVersion);
writer.IncludeForwardedTypes = FollowTypeForwards;
writer.DefaultCondition = DefaultCondition;
if (ConditionalTypeLists != null)
{
writer.ConditionalTypeLists = ConditionalTypeLists.Select(c =>
new CSharpWriter.ConditionalTypeList
{
Symbol = c.GetMetadata("Symbol"),
Filter = new DocIdIncludeListFilter(c.ItemSpec) { IncludeForwardedTypes = FollowTypeForwards }
});
}
return writer;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
Assembly="$(GenAPIInputAssembly)"
LibPath="$(GenAPILibPath)"
ApiList="$(GenAPIApiList)"
ConditionalTypeLists="@(GenAPIConditionalTypeLists)"
DefaultCondition="$(GenAPIDefaultCondition)"
OutputPath="$(GenAPITargetPath)"
HeaderFile="$(GenAPIHeaderFile)"
WriterType="$(GenAPIWriterType)"
Expand Down