// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// This file is ported and adapted from ComputeSharp (Sergio0694/ComputeSharp),
// more info in ThirdPartyNotices.txt in the root of the project.
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
namespace CommunityToolkit.Mvvm.SourceGenerators.Models;
///
partial record HierarchyInfo
{
///
/// Creates a instance wrapping the given members.
///
/// The input instances to use.
/// The optional instance to add to generated types.
/// A object wrapping .
public CompilationUnitSyntax GetCompilationUnit(
ImmutableArray memberDeclarations,
BaseListSyntax? baseList = null)
{
// Create the partial type declaration with the given member declarations.
// This code produces a class declaration as follows:
//
// partial TYPE_NAME>
// {
//
// }
TypeDeclarationSyntax typeDeclarationSyntax =
Hierarchy[0].GetSyntax()
.AddModifiers(Token(SyntaxKind.PartialKeyword))
.AddMembers(memberDeclarations.ToArray());
// Add the base list, if present
if (baseList is not null)
{
typeDeclarationSyntax = typeDeclarationSyntax.WithBaseList(baseList);
}
// Add all parent types in ascending order, if any
foreach (TypeInfo parentType in Hierarchy.AsSpan().Slice(1))
{
typeDeclarationSyntax =
parentType.GetSyntax()
.AddModifiers(Token(SyntaxKind.PartialKeyword))
.AddMembers(typeDeclarationSyntax);
}
// Prepare the leading trivia for the generated compilation unit.
// This will produce code as follows:
//
//
// #pragma warning disable
// #nullable enable
SyntaxTriviaList syntaxTriviaList = TriviaList(
Comment("// "),
Trivia(PragmaWarningDirectiveTrivia(Token(SyntaxKind.DisableKeyword), true)),
Trivia(NullableDirectiveTrivia(Token(SyntaxKind.EnableKeyword), true)));
if (Namespace is "")
{
// If there is no namespace, attach the pragma directly to the declared type,
// and skip the namespace declaration. This will produce code as follows:
//
//
//
return
CompilationUnit()
.AddMembers(typeDeclarationSyntax.WithLeadingTrivia(syntaxTriviaList))
.NormalizeWhitespace();
}
// Create the compilation unit with disabled warnings, target namespace and generated type.
// This will produce code as follows:
//
//
// namespace
// {
//
// }
return
CompilationUnit().AddMembers(
NamespaceDeclaration(IdentifierName(Namespace))
.WithLeadingTrivia(syntaxTriviaList)
.AddMembers(typeDeclarationSyntax))
.NormalizeWhitespace();
}
}