microsoft/healthcare-shared-components

Public

mirrored from https://github.com/microsoft/healthcare-shared-componentsAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1.0.0-1.0.79

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/TypeExtensions.cs

86lines · modecode

1// -------------------------------------------------------------------------------------------------
2// Copyright (c) Microsoft Corporation. All rights reserved.
3// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
4// -------------------------------------------------------------------------------------------------
5
6using System;
7using System.Collections.Generic;
8using System.Linq;
9using Microsoft.CodeAnalysis;
10using Microsoft.CodeAnalysis.CSharp;
11using Microsoft.CodeAnalysis.CSharp.Syntax;
12
13namespace Microsoft.Health.Extensions.BuildTimeCodeGenerator
14{
15 internal static class TypeExtensions
16 {
17 /// <summary>
18 /// Converts a <see cref="Type"/> to a <see cref="TypeSyntax"/>.
19 /// </summary>
20 /// <param name="t">The type</param>
21 /// <param name="useGlobalAlias">Whether the to qualify type names with "global::"</param>
22 /// <returns>A <see cref="TypeSyntax"/> representing the type.</returns>
23 public static TypeSyntax ToTypeSyntax(this Type t, bool useGlobalAlias = false)
24 {
25 if (t == typeof(void))
26 {
27 return SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.VoidKeyword));
28 }
29
30 if (t.IsGenericParameter)
31 {
32 return SyntaxFactory.IdentifierName(t.Name);
33 }
34
35 if (t.IsArray)
36 {
37 return SyntaxFactory.ArrayType(
38 t.GetElementType().ToTypeSyntax(useGlobalAlias),
39 SyntaxFactory.SingletonList(
40 SyntaxFactory.ArrayRankSpecifier(
41 SyntaxFactory.SingletonSeparatedList<ExpressionSyntax>(
42 SyntaxFactory.OmittedArraySizeExpression()))));
43 }
44
45 if (t.IsPointer)
46 {
47 return SyntaxFactory.PointerType(t.GetElementType().ToTypeSyntax(useGlobalAlias));
48 }
49
50 TypeSyntax qualification = t.IsNested
51 ? t.DeclaringType.ToTypeSyntax(useGlobalAlias)
52 : t.Namespace.Split('.')
53 .Select(s => (NameSyntax)SyntaxFactory.IdentifierName(s))
54 .Aggregate((acc, next) =>
55 {
56 // see if we should qualify with global::
57 NameSyntax left = useGlobalAlias && acc is IdentifierNameSyntax identifier
58 ? SyntaxFactory.AliasQualifiedName(SyntaxFactory.IdentifierName(SyntaxFactory.Token(SyntaxKind.GlobalKeyword)), identifier)
59 : acc;
60
61 return SyntaxFactory.QualifiedName(left, (SimpleNameSyntax)next);
62 });
63
64 SimpleNameSyntax name = t.IsGenericType
65 ? SyntaxFactory.GenericName(t.Name.Substring(0, t.Name.IndexOf('`', StringComparison.Ordinal)))
66 .WithTypeArgumentList(SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(t.GenericTypeArguments.Select(typeArg => typeArg.ToTypeSyntax(useGlobalAlias)))))
67 : (SimpleNameSyntax)SyntaxFactory.IdentifierName(t.Name);
68
69 return SyntaxFactory.QualifiedName((NameSyntax)qualification, name);
70 }
71
72 /// <summary>
73 /// Creates a closed generic type from the a generic type definition (like <see cref="IEnumerable{T}"/>) and type arguments (like <see cref="string"/>).
74 /// </summary>
75 /// <param name="genericTypeDefinition">The generic type definition</param>
76 /// <param name="typeArguments">Type arguments</param>
77 /// <returns>The generic type.</returns>
78 public static TypeSyntax CreateGenericTypeFromGenericTypeDefinition(TypeSyntax genericTypeDefinition, params TypeSyntax[] typeArguments)
79 {
80 GenericNameSyntax openType = genericTypeDefinition.DescendantNodes().OfType<GenericNameSyntax>().Single();
81 GenericNameSyntax closedType = openType.AddTypeArgumentListArguments(typeArguments);
82
83 return genericTypeDefinition.ReplaceNode(openType, closedType);
84 }
85 }
86}