KEMBAR78
Simple Ref | PDF | Object Oriented Programming | Computing
0% found this document useful (0 votes)
24 views3 pages

Simple Ref

The document defines a C# class library for finding and managing specifiers related to Unreal Engine's UHT (Unreal Header Tool). It includes a method for discovering supported specifiers using reflection, along with a mapping of table names to corresponding tags. The code also outlines the structure of known specifier information and the associated tags used in Unreal Engine development.

Uploaded by

lecocoy949
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views3 pages

Simple Ref

The document defines a C# class library for finding and managing specifiers related to Unreal Engine's UHT (Unreal Header Tool). It includes a method for discovering supported specifiers using reflection, along with a mapping of table names to corresponding tags. The code also outlines the structure of known specifier information and the associated tags used in Unreal Engine development.

Uploaded by

lecocoy949
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 3

// Copyright (c) 2024 citrus - https://unrealist.

org
// Licensed under the MIT License.

using System;

namespace Citrus.Plugins.SpecifierReferenceViewer.ReferenceGenerator;

// Copyright (c) 2024 citrus - https://unrealist.org


// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using EpicGames.UHT.Tables;
using EpicGames.UHT.Types;
using EpicGames.UHT.Utils;
using static Citrus.Plugins.SpecifierReferenceViewer.ReferenceGenerator.Tag;

namespace Citrus.Plugins.SpecifierReferenceViewer.ReferenceGenerator;

/// <summary>
/// Provides information about a valid specifier for one or more tags.
/// </summary>
internal sealed record KnownSpecifierInfo(string SpecifierName, Tag Tag,
UhtSpecifierValueType ValueType);

/// <summary>
/// Provides a method for finding all supported specifiers using reflection.
/// </summary>
internal static class SpecifierFinder
{
/// <summary>
/// A list of assemblies to search for specifiers.
/// </summary>
private static readonly IReadOnlyList<Assembly> AssembliesToSearch = new[]
{
// The UHT itself is included.
typeof(UhtType).Assembly
};

/// <summary>
/// A map between a table name to one or more tags that can use the specifier.
/// </summary>
private static readonly IReadOnlyDictionary<string, Tag> TableNameToTag = new
Dictionary<string, Tag>
{
[UhtTableNames.ClassBase] = UCLASS | UINTERFACE,
[UhtTableNames.Class] = UCLASS,
[UhtTableNames.Default] = UPROPERTY | UCLASS | USTRUCT | UENUM | UMETA |
UPARAM | UINTERFACE | UDELEGATE | UFUNCTION,
[UhtTableNames.Enum] = UENUM,
[UhtTableNames.Field] = UCLASS | UENUM | UFUNCTION | USTRUCT | UDELEGATE |
UINTERFACE,
[UhtTableNames.Function] = UFUNCTION | UDELEGATE,
[UhtTableNames.Interface] = UINTERFACE,
[UhtTableNames.PropertyArgument] = UPARAM,
[UhtTableNames.PropertyMember] = UPROPERTY,
[UhtTableNames.ScriptStruct] = USTRUCT
};

/// <summary>
/// Finds all supported specifiers.
/// </summary>
public static IEnumerable<KnownSpecifierInfo> FindAllSpecifiers()
{
Dictionary<string, KnownSpecifierInfo> dedupedSpecifiers = new();

foreach (KnownSpecifierInfo specifier in FindAllSpecifiersInAssemblies())


{
if (dedupedSpecifiers.TryGetValue(specifier.SpecifierName, out
KnownSpecifierInfo? existingSpecifierInfo))
{
dedupedSpecifiers[specifier.SpecifierName] =
existingSpecifierInfo with
{
Tag = specifier.Tag | existingSpecifierInfo.Tag
};
}
else
{
dedupedSpecifiers.Add(specifier.SpecifierName, specifier);
}
}

return dedupedSpecifiers.Values;
}

/// <summary>
/// Uses reflection against UHT to find all supported specifiers. This will
produce duplicate specifiers for each
/// supported tag.
/// </summary>
private static IEnumerable<KnownSpecifierInfo> FindAllSpecifiersInAssemblies()
{
const BindingFlags methodSearchFlags
= BindingFlags.Public
| BindingFlags.NonPublic
| BindingFlags.DeclaredOnly
| BindingFlags.Instance
| BindingFlags.Static;

foreach (Assembly assembly in AssembliesToSearch)


{
var specifiers = from type in assembly.GetTypes()
from method in type.GetMethods(methodSearchFlags)
from attribute in
method.GetCustomAttributes<UhtSpecifierAttribute>()
select CreateSpecifierInfo(type, method, attribute);

foreach (var specifier in specifiers)


{
if (specifier is not null)
{
yield return specifier;
}
}
}
}

/// <summary>
/// Extracts information about a specifier from reflection data.
/// </summary>
private static KnownSpecifierInfo? CreateSpecifierInfo(
Type @class, MethodInfo methodInfo, UhtSpecifierAttribute attribute)
{
// Use the explicit name of the specifier if set; otherwise, get it from
the method name.
string specifierName = UhtLookupTableBase.GetSuffixedName(@class,
methodInfo, attribute.Name, "Specifier");

if (!string.IsNullOrEmpty(attribute.Extends) && attribute.ValueType is not


UhtSpecifierValueType.NotSet)
{
return new KnownSpecifierInfo(specifierName,
TableNameToTag[attribute.Extends], attribute.ValueType);
}

return null;
}
}

/// <summary>
/// Indicates the tag that contains a specifier or metadata.
/// </summary>
[Flags]
public enum Tag
{
UPROPERTY = 1,
UCLASS = 2,
USTRUCT = 4,
UENUM = 8,
UMETA = 16,
UPARAM = 32,
UINTERFACE = 64,
UDELEGATE = 128,
UFUNCTION = 256,
}

You might also like