diff --git a/src/Microsoft.DotNet.GenFacades/NotSupportedAssemblyGenerator.cs b/src/Microsoft.DotNet.GenFacades/NotSupportedAssemblyGenerator.cs
index 467858088e8..898caaaeb94 100644
--- a/src/Microsoft.DotNet.GenFacades/NotSupportedAssemblyGenerator.cs
+++ b/src/Microsoft.DotNet.GenFacades/NotSupportedAssemblyGenerator.cs
@@ -14,7 +14,8 @@
namespace Microsoft.DotNet.GenFacades
{
///
- /// The class generates an NotSupportedAssembly from the reference sources.
+ /// Generates a not-supported assembly from reference sources, optionally enriching
+ /// XML documentation comments from implementation sources in the same project.
///
public class NotSupportedAssemblyGenerator : RoslynBuildTask
{
@@ -28,11 +29,18 @@ public class NotSupportedAssemblyGenerator : RoslynBuildTask
public string ApiExclusionListPath { get; set; }
+ ///
+ /// Optional implementation source files (e.g. **/*.cs for the current project)
+ /// used to provide XML doc comments for the generated not-supported stubs.
+ /// Warnings are emitted for public APIs that cannot be located or lack documentation.
+ ///
+ public ITaskItem[] ImplementationSourceFiles { get; set; }
+
public override bool ExecuteCore()
{
if (SourceFiles == null || SourceFiles.Length == 0)
{
- Log.LogError("There are no ref source files.");
+ Log.LogError("There are no source files.");
return false;
}
@@ -49,6 +57,15 @@ private void GenerateNotSupportedAssemblyFiles(IEnumerable sourceFile
apiExclusions = File.ReadAllLines(ApiExclusionListPath);
}
+ LanguageVersion languageVersion = LanguageVersion.Default;
+ if (!string.IsNullOrEmpty(LangVersion) && !LanguageVersionFacts.TryParse(LangVersion, out languageVersion))
+ {
+ Log.LogError($"Invalid LangVersion value '{LangVersion}'");
+ return;
+ }
+
+ DocCommentIndex docIndex = BuildDocCommentIndex(languageVersion);
+
foreach (ITaskItem item in sourceFiles)
{
string sourceFile = item.ItemSpec;
@@ -60,164 +77,451 @@ private void GenerateNotSupportedAssemblyFiles(IEnumerable sourceFile
continue;
}
- GenerateNotSupportedAssemblyForSourceFile(sourceFile, outputPath, apiExclusions);
+ GenerateNotSupportedAssemblyForSourceFile(sourceFile, outputPath, apiExclusions, languageVersion, docIndex);
}
}
- private void GenerateNotSupportedAssemblyForSourceFile(string sourceFile, string outputPath, string[] apiExclusions)
+ private DocCommentIndex BuildDocCommentIndex(LanguageVersion languageVersion)
{
- SyntaxTree syntaxTree;
+ if (ImplementationSourceFiles == null || ImplementationSourceFiles.Length == 0)
+ return null;
- try
+ var parseOptions = new CSharpParseOptions(languageVersion);
+ var index = new DocCommentIndex();
+
+ foreach (ITaskItem item in ImplementationSourceFiles)
{
- LanguageVersion languageVersion = LanguageVersion.Default;
- if (!String.IsNullOrEmpty(LangVersion) && !LanguageVersionFacts.TryParse(LangVersion, out languageVersion))
+ string path = item.ItemSpec;
+ if (!File.Exists(path))
+ continue;
+
+ try
{
- Log.LogError($"Invalid LangVersion value '{LangVersion}'");
- return;
+ SyntaxTree tree = CSharpSyntaxTree.ParseText(File.ReadAllText(path), parseOptions);
+ index.AddSourceTree(tree);
}
+ catch (Exception ex)
+ {
+ Log.LogWarning($"Failed to parse implementation source '{path}': {ex.Message}");
+ }
+ }
+
+ return index;
+ }
+
+ private void GenerateNotSupportedAssemblyForSourceFile(
+ string sourceFile,
+ string outputPath,
+ string[] apiExclusions,
+ LanguageVersion languageVersion,
+ DocCommentIndex docIndex)
+ {
+ SyntaxTree syntaxTree;
+
+ try
+ {
syntaxTree = CSharpSyntaxTree.ParseText(File.ReadAllText(sourceFile), new CSharpParseOptions(languageVersion));
}
- catch(Exception ex)
+ catch (Exception ex)
{
Log.LogErrorFromException(ex, false);
return;
}
- var rewriter = new NotSupportedAssemblyRewriter(Message, apiExclusions);
+ var rewriter = new NotSupportedAssemblyRewriter(Message, apiExclusions, docIndex);
SyntaxNode root = rewriter.Visit(syntaxTree.GetRoot());
string text = root.GetText().ToString();
File.WriteAllText(outputPath, text);
+
+ if (docIndex != null)
+ {
+ foreach (string api in rewriter.ApisNotFoundInImplementation)
+ Log.LogWarning($"Public API '{api}' could not be located in implementation sources.");
+
+ foreach (string api in rewriter.ApisMissingDocumentation)
+ Log.LogWarning($"Public API '{api}' is missing documentation in implementation sources.");
+ }
}
}
- internal class NotSupportedAssemblyRewriter : CSharpSyntaxRewriter
+ ///
+ /// Builds a lookup from public API keys to their XML doc comment trivia,
+ /// collected from one or more implementation source files. First occurrence wins.
+ ///
+ internal sealed class DocCommentIndex
{
- private const string emptyBody = "{ }\n";
- private string _message;
- private IEnumerable _exclusionApis;
+ // All APIs seen in implementation sources (with or without docs).
+ private readonly HashSet _seenApis = new(StringComparer.Ordinal);
+ // APIs that have at least one XML doc comment (first occurrence wins).
+ private readonly Dictionary _docTrivia = new(StringComparer.Ordinal);
- public NotSupportedAssemblyRewriter(string message, string[] exclusionApis)
+ public void AddSourceTree(SyntaxTree tree)
{
- if (message != null && message.StartsWith("SR."))
- {
- _message = "System." + message;
- }
- else
+ var walker = new DocCommentWalker(this);
+ walker.Visit(tree.GetRoot());
+ }
+
+ internal void RecordMember(string key, SyntaxTriviaList leading)
+ {
+ _seenApis.Add(key);
+
+ if (!_docTrivia.ContainsKey(key))
{
- _message = message;
+ var docTrivia = leading
+ .Where(t => t.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia) ||
+ t.IsKind(SyntaxKind.MultiLineDocumentationCommentTrivia))
+ .ToList();
+
+ if (docTrivia.Count > 0)
+ _docTrivia[key] = SyntaxFactory.TriviaList(docTrivia);
}
- _exclusionApis = exclusionApis?.Select(t => t.Substring(t.IndexOf(':') + 1));
}
- public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
+ public bool HasMember(string key) => _seenApis.Contains(key);
+
+ public bool TryGetDocComment(string key, out SyntaxTriviaList docTrivia)
+ => _docTrivia.TryGetValue(key, out docTrivia);
+ }
+
+ ///
+ /// Walks an implementation source tree and records doc comment trivia for all declared members.
+ ///
+ internal sealed class DocCommentWalker : CSharpSyntaxWalker
+ {
+ private readonly DocCommentIndex _index;
+
+ public DocCommentWalker(DocCommentIndex index) { _index = index; }
+
+ public override void VisitClassDeclaration(ClassDeclarationSyntax node)
{
- if (node.Body == null)
- return node;
+ _index.RecordMember(ApiKey.GetTypeKey(node), node.GetLeadingTrivia());
+ base.VisitClassDeclaration(node);
+ }
- if (_exclusionApis != null && _exclusionApis.Contains(GetMethodDefinition(node)))
- return null;
+ public override void VisitStructDeclaration(StructDeclarationSyntax node)
+ {
+ _index.RecordMember(ApiKey.GetTypeKey(node), node.GetLeadingTrivia());
+ base.VisitStructDeclaration(node);
+ }
+
+ public override void VisitInterfaceDeclaration(InterfaceDeclarationSyntax node)
+ {
+ _index.RecordMember(ApiKey.GetTypeKey(node), node.GetLeadingTrivia());
+ base.VisitInterfaceDeclaration(node);
+ }
+
+ public override void VisitRecordDeclaration(RecordDeclarationSyntax node)
+ {
+ _index.RecordMember(ApiKey.GetTypeKey(node), node.GetLeadingTrivia());
+ base.VisitRecordDeclaration(node);
+ }
+
+ public override void VisitEnumDeclaration(EnumDeclarationSyntax node)
+ {
+ _index.RecordMember(ApiKey.GetEnumKey(node), node.GetLeadingTrivia());
+ base.VisitEnumDeclaration(node);
+ }
+
+ public override void VisitDelegateDeclaration(DelegateDeclarationSyntax node)
+ {
+ _index.RecordMember(ApiKey.GetDelegateKey(node), node.GetLeadingTrivia());
+ }
+
+ public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax node)
+ {
+ if (node.Parent is TypeDeclarationSyntax parent)
+ _index.RecordMember(ApiKey.GetMemberKey(parent, ".ctor"), node.GetLeadingTrivia());
+ }
+
+ public override void VisitDestructorDeclaration(DestructorDeclarationSyntax node)
+ {
+ if (node.Parent is TypeDeclarationSyntax parent)
+ _index.RecordMember(ApiKey.GetMemberKey(parent, "Finalize"), node.GetLeadingTrivia());
+ }
+
+ public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
+ {
+ if (node.Parent is TypeDeclarationSyntax parent)
+ _index.RecordMember(ApiKey.GetMemberKey(parent, node.Identifier.ValueText), node.GetLeadingTrivia());
+ }
+
+ public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node)
+ {
+ if (node.Parent is TypeDeclarationSyntax parent)
+ _index.RecordMember(ApiKey.GetMemberKey(parent, node.Identifier.ValueText), node.GetLeadingTrivia());
+ }
- BlockSyntax block;
- if (node.Identifier.ValueText == "Dispose" || node.Identifier.ValueText == "Finalize")
+ public override void VisitEventDeclaration(EventDeclarationSyntax node)
+ {
+ if (node.Parent is TypeDeclarationSyntax parent)
+ _index.RecordMember(ApiKey.GetMemberKey(parent, node.Identifier.ValueText), node.GetLeadingTrivia());
+ }
+
+ public override void VisitEventFieldDeclaration(EventFieldDeclarationSyntax node)
+ {
+ if (node.Parent is TypeDeclarationSyntax parent)
{
- block = (BlockSyntax)SyntaxFactory.ParseStatement(emptyBody);
+ foreach (VariableDeclaratorSyntax v in node.Declaration.Variables)
+ _index.RecordMember(ApiKey.GetMemberKey(parent, v.Identifier.ValueText), node.GetLeadingTrivia());
}
- else
+ }
+
+ public override void VisitFieldDeclaration(FieldDeclarationSyntax node)
+ {
+ if (node.Parent is TypeDeclarationSyntax parent)
{
- block = (BlockSyntax)SyntaxFactory.ParseStatement(GetDefaultMessage());
+ foreach (VariableDeclaratorSyntax v in node.Declaration.Variables)
+ _index.RecordMember(ApiKey.GetMemberKey(parent, v.Identifier.ValueText), node.GetLeadingTrivia());
}
- return node.WithBody(block);
}
- public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
+ public override void VisitOperatorDeclaration(OperatorDeclarationSyntax node)
+ {
+ if (node.Parent is TypeDeclarationSyntax parent)
+ _index.RecordMember(ApiKey.GetOperatorKey(parent, node.OperatorToken.ValueText), node.GetLeadingTrivia());
+ }
+
+ public override void VisitConversionOperatorDeclaration(ConversionOperatorDeclarationSyntax node)
+ {
+ if (node.Parent is TypeDeclarationSyntax parent)
+ _index.RecordMember(ApiKey.GetConversionOperatorKey(parent, node.ImplicitOrExplicitKeyword.ValueText), node.GetLeadingTrivia());
+ }
+
+ public override void VisitEnumMemberDeclaration(EnumMemberDeclarationSyntax node)
+ {
+ if (node.Parent is EnumDeclarationSyntax parentEnum)
+ _index.RecordMember(ApiKey.GetEnumKey(parentEnum) + "." + node.Identifier.ValueText, node.GetLeadingTrivia());
+ }
+ }
+
+ ///
+ /// Helpers for computing consistent, fully-qualified API keys from syntax nodes.
+ /// Handles regular namespaces, file-scoped namespaces, nested types, and top-level types.
+ ///
+ internal static class ApiKey
+ {
+ public static string GetTypeKey(TypeDeclarationSyntax node)
+ => Qualify(GetParentPrefix(node.Parent), node.Identifier.ValueText.Trim());
+
+ public static string GetEnumKey(EnumDeclarationSyntax node)
+ => Qualify(GetParentPrefix(node.Parent), node.Identifier.ValueText.Trim());
+
+ public static string GetDelegateKey(DelegateDeclarationSyntax node)
+ => Qualify(GetParentPrefix(node.Parent), node.Identifier.ValueText.Trim());
+
+ public static string GetMemberKey(TypeDeclarationSyntax parent, string memberName)
+ => GetTypeKey(parent) + "." + memberName;
+
+ public static string GetOperatorKey(TypeDeclarationSyntax parent, string operatorToken)
+ => GetTypeKey(parent) + ".op_" + operatorToken;
+
+ public static string GetConversionOperatorKey(TypeDeclarationSyntax parent, string implicitOrExplicit)
+ => GetTypeKey(parent) + "." + implicitOrExplicit + " operator";
+
+ private static string GetParentPrefix(SyntaxNode parent) => parent switch
+ {
+ NamespaceDeclarationSyntax ns => ns.Name.ToFullString().Trim(),
+ FileScopedNamespaceDeclarationSyntax fns => fns.Name.ToFullString().Trim(),
+ TypeDeclarationSyntax type => GetTypeKey(type),
+ _ => string.Empty,
+ };
+
+ private static string Qualify(string prefix, string name)
+ => string.IsNullOrEmpty(prefix) ? name : prefix + "." + name;
+ }
+
+ internal class NotSupportedAssemblyRewriter : CSharpSyntaxRewriter
+ {
+ private readonly string _message;
+ private readonly IEnumerable _exclusionApis;
+ private readonly DocCommentIndex _docIndex;
+ private readonly List _apisNotFoundInImplementation = new();
+ private readonly List _apisMissingDocs = new();
+
+ public IReadOnlyList ApisNotFoundInImplementation => _apisNotFoundInImplementation;
+ public IReadOnlyList ApisMissingDocumentation => _apisMissingDocs;
+
+ public NotSupportedAssemblyRewriter(string message, string[] exclusionApis, DocCommentIndex docIndex = null)
+ {
+ _message = message != null && message.StartsWith("SR.") ? "System." + message : message;
+ _exclusionApis = exclusionApis?.Select(t => t.Substring(t.IndexOf(':') + 1));
+ _docIndex = docIndex;
+ }
+
+ public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
{
- if (_exclusionApis != null && _exclusionApis.Contains(GetPropertyDefinition(node)))
+ string key = ApiKey.GetTypeKey(node);
+ if (_exclusionApis != null && _exclusionApis.Contains(key))
return null;
- return base.VisitPropertyDeclaration(node);
+ SyntaxNode result = base.VisitClassDeclaration(node);
+ return ApplyDocComment(result, key);
}
- public override SyntaxNode VisitEventDeclaration(EventDeclarationSyntax node)
+ public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
{
- if (_exclusionApis != null && _exclusionApis.Contains(GetEventDefinition(node)))
+ // Abstract/extern methods and interface members have neither body nor expression body.
+ if (node.Body == null && node.ExpressionBody == null)
+ return node;
+
+ string key = ApiKey.GetMemberKey((TypeDeclarationSyntax)node.Parent, node.Identifier.ValueText);
+ if (_exclusionApis != null && _exclusionApis.Contains(key))
return null;
- return base.VisitEventDeclaration(node);
+ BlockSyntax block = node.Identifier.ValueText == "Dispose" || node.Identifier.ValueText == "Finalize"
+ ? CreateEmptyBlock()
+ : CreateThrowBlock();
+ SyntaxNode result = node.WithBody(block).WithExpressionBody(null).WithSemicolonToken(default);
+ return ApplyDocComment(result, key);
}
- public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
+ public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
+ {
+ string key = ApiKey.GetMemberKey((TypeDeclarationSyntax)node.Parent, node.Identifier.ValueText);
+ if (_exclusionApis != null && _exclusionApis.Contains(key))
+ return null;
+
+ SyntaxNode result;
+
+ // Handle expression-bodied properties (e.g., `public int X => _x;`).
+ // Convert them to a getter-only property that throws.
+ if (node.ExpressionBody != null)
+ {
+ var getterAccessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
+ .WithBody(CreateThrowBlock());
+ var accessorList = SyntaxFactory.AccessorList(SyntaxFactory.SingletonList(getterAccessor));
+ result = node.WithExpressionBody(null)
+ .WithSemicolonToken(default)
+ .WithInitializer(null)
+ .WithAccessorList(accessorList);
+ }
+ else
+ {
+ // Strip property initializers (e.g., `public int X { get; } = 5;`).
+ if (node.Initializer != null)
+ node = node.WithInitializer(null).WithSemicolonToken(default);
+
+ result = base.VisitPropertyDeclaration(node);
+ }
+
+ return ApplyDocComment(result, key);
+ }
+
+ public override SyntaxNode VisitEventDeclaration(EventDeclarationSyntax node)
{
- if (_exclusionApis != null && _exclusionApis.Contains(GetFullyQualifiedName(node)))
+ string key = ApiKey.GetMemberKey((TypeDeclarationSyntax)node.Parent, node.Identifier.ValueText);
+ if (_exclusionApis != null && _exclusionApis.Contains(key))
return null;
- return base.VisitClassDeclaration(node);
+ SyntaxNode result = base.VisitEventDeclaration(node);
+ return ApplyDocComment(result, key);
}
public override SyntaxNode VisitConstructorDeclaration(ConstructorDeclarationSyntax node)
{
- BlockSyntax block = (BlockSyntax)SyntaxFactory.ParseStatement(GetDefaultMessage());
- return node.WithBody(block);
+ string key = ApiKey.GetMemberKey((TypeDeclarationSyntax)node.Parent, ".ctor");
+ SyntaxNode result = node.WithBody(CreateThrowBlock()).WithExpressionBody(null).WithSemicolonToken(default);
+ return ApplyDocComment(result, key);
}
public override SyntaxNode VisitDestructorDeclaration(DestructorDeclarationSyntax node)
{
- BlockSyntax block = (BlockSyntax)SyntaxFactory.ParseStatement(emptyBody);
- return node.WithBody(block);
+ return node.WithBody(CreateEmptyBlock()).WithExpressionBody(null).WithSemicolonToken(default);
}
public override SyntaxNode VisitAccessorDeclaration(AccessorDeclarationSyntax node)
{
- if (node.Body == null)
+ // Auto-accessors and interface accessors have neither body nor expression body.
+ if (node.Body == null && node.ExpressionBody == null)
return node;
- string message = "{ throw new System.PlatformNotSupportedException(" + $"{ _message }); "+ " } ";
- BlockSyntax block = (BlockSyntax)SyntaxFactory.ParseStatement(message);
-
- return node.WithBody(block);
+ return node.WithBody(CreateThrowBlock()).WithExpressionBody(null).WithSemicolonToken(default);
}
public override SyntaxNode VisitOperatorDeclaration(OperatorDeclarationSyntax node)
{
- if (node.Body == null)
+ if (node.Body == null && node.ExpressionBody == null)
return node;
- BlockSyntax block = (BlockSyntax)SyntaxFactory.ParseStatement(GetDefaultMessage());
- return node.WithBody(block);
+ string key = ApiKey.GetOperatorKey((TypeDeclarationSyntax)node.Parent, node.OperatorToken.ValueText);
+ SyntaxNode result = node.WithBody(CreateThrowBlock()).WithExpressionBody(null).WithSemicolonToken(default);
+ return ApplyDocComment(result, key);
}
public override SyntaxNode VisitConversionOperatorDeclaration(ConversionOperatorDeclarationSyntax node)
{
- if (node.Body == null)
+ if (node.Body == null && node.ExpressionBody == null)
return node;
- BlockSyntax block = (BlockSyntax)SyntaxFactory.ParseStatement(GetDefaultMessage());
- return node.WithBody(block);
+ string key = ApiKey.GetConversionOperatorKey((TypeDeclarationSyntax)node.Parent, node.ImplicitOrExplicitKeyword.ValueText);
+ SyntaxNode result = node.WithBody(CreateThrowBlock()).WithExpressionBody(null).WithSemicolonToken(default);
+ return ApplyDocComment(result, key);
}
- private string GetFullyQualifiedName(TypeDeclarationSyntax node)
+ public override SyntaxNode VisitVariableDeclarator(VariableDeclaratorSyntax node)
{
- string parent;
- if (node.Parent is NamespaceDeclarationSyntax parentNamespace)
+ // Strip non-const field initializers so that implementation sources with runtime
+ // initializers (e.g., `private static readonly X s_x = new X();`) compile correctly.
+ if (node.Initializer != null &&
+ node.Parent is VariableDeclarationSyntax &&
+ node.Parent.Parent is FieldDeclarationSyntax fieldDecl &&
+ !fieldDecl.Modifiers.Any(SyntaxKind.ConstKeyword))
{
- parent = GetFullyQualifiedName(parentNamespace);
- }
- else
- {
- parent = GetFullyQualifiedName((TypeDeclarationSyntax)node.Parent);
+ return node.WithInitializer(null);
}
- return parent + "." + node.Identifier.ValueText.Trim();
+ return base.VisitVariableDeclarator(node);
}
- private string GetFullyQualifiedName(NamespaceDeclarationSyntax node) => node.Name.ToFullString().Trim();
+ ///
+ /// If implementation sources are available, replaces the node's XML doc comment trivia
+ /// with the implementation's doc comment. Records a warning-level diagnostic if the API
+ /// could not be found or has no documentation.
+ ///
+ private SyntaxNode ApplyDocComment(SyntaxNode node, string key)
+ {
+ if (_docIndex == null || node == null)
+ return node;
- private string GetMethodDefinition(MethodDeclarationSyntax node) => GetFullyQualifiedName((TypeDeclarationSyntax)node.Parent) + "." + node.Identifier.ValueText;
+ if (_docIndex.TryGetDocComment(key, out SyntaxTriviaList implDocTrivia))
+ {
+ return node.WithLeadingTrivia(ReplaceDocTrivia(node.GetLeadingTrivia(), implDocTrivia));
+ }
- private string GetPropertyDefinition(PropertyDeclarationSyntax node) => GetFullyQualifiedName((TypeDeclarationSyntax)node.Parent) + "." + node.Identifier.ValueText;
+ if (!_docIndex.HasMember(key))
+ _apisNotFoundInImplementation.Add(key);
+ else
+ _apisMissingDocs.Add(key);
- private string GetEventDefinition(EventDeclarationSyntax node) => GetFullyQualifiedName((TypeDeclarationSyntax)node.Parent) + "." + node.Identifier.ValueText;
+ return node;
+ }
+
+ ///
+ /// Replaces any XML doc comment trivia in with
+ /// , preserving surrounding whitespace/indentation.
+ ///
+ private static SyntaxTriviaList ReplaceDocTrivia(SyntaxTriviaList existing, SyntaxTriviaList implDocs)
+ {
+ // Remove existing doc-comment trivia.
+ var withoutDocs = existing
+ .Where(t => !t.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia) &&
+ !t.IsKind(SyntaxKind.MultiLineDocumentationCommentTrivia))
+ .ToList();
+
+ // Insert implementation docs just before the trailing indentation whitespace that
+ // immediately precedes the declaration keyword.
+ int insertAt = withoutDocs.Count;
+ while (insertAt > 0 && withoutDocs[insertAt - 1].IsKind(SyntaxKind.WhitespaceTrivia))
+ insertAt--;
+
+ withoutDocs.InsertRange(insertAt, implDocs);
+ return SyntaxFactory.TriviaList(withoutDocs);
+ }
private string GetDefaultMessage() => "{ throw new System.PlatformNotSupportedException(" + $"{ _message }); " + " }\n";
+
+ private BlockSyntax CreateThrowBlock() => (BlockSyntax)SyntaxFactory.ParseStatement(GetDefaultMessage());
+
+ private static BlockSyntax CreateEmptyBlock() => (BlockSyntax)SyntaxFactory.ParseStatement("{ }\n");
}
}
diff --git a/src/Microsoft.DotNet.GenFacades/build/Microsoft.DotNet.GenFacades.NotSupported.targets b/src/Microsoft.DotNet.GenFacades/build/Microsoft.DotNet.GenFacades.NotSupported.targets
index 46a061c0f5a..7d5c8865e2c 100644
--- a/src/Microsoft.DotNet.GenFacades/build/Microsoft.DotNet.GenFacades.NotSupported.targets
+++ b/src/Microsoft.DotNet.GenFacades/build/Microsoft.DotNet.GenFacades.NotSupported.targets
@@ -18,8 +18,22 @@
+
+
+
+
+
-
+
SourceFilesProjectOutputGroup
false
_contractSourceFilesGroup
@@ -29,7 +43,7 @@
-
+