Name sanitization overhaul in progress

This commit is contained in:
2026-03-28 21:07:28 -04:00
parent 22fe60f431
commit 9790fa34e1
6 changed files with 41 additions and 71 deletions

View File

@@ -44,7 +44,7 @@ bool UWingComponentReference::CheckExists(UWingComponentReference::FoundComponen
{
if ((FC.SCS == nullptr) && (FC.Native == nullptr))
{
UWingServer::Printf(TEXT("Cannot find component: %s\n"), *WingUtils::SanitizeName(FC.Name));
UWingServer::Printf(TEXT("Cannot find component: %s\n"), *WingUtils::ExternalizeID(FC.Name));
return false;
}
return true;
@@ -55,19 +55,19 @@ bool UWingComponentReference::CheckValidParent(UWingComponentReference::FoundCom
if (FC.SCS && FC.Native)
{
UWingServer::Printf(TEXT("Weirdness, two components named %s\n"),
*WingUtils::SanitizeName(FC.Name));
*WingUtils::ExternalizeID(FC.Name));
return false;
}
if ((FC.SCS == nullptr) && (FC.Native == nullptr))
{
UWingServer::Printf(TEXT("No such parent component: %s\n"),
*WingUtils::SanitizeName(FC.Name));
*WingUtils::ExternalizeID(FC.Name));
return false;
}
if (FC.Native && (!Cast<USceneComponent>(FC.Native)))
{
UWingServer::Printf(TEXT("Not a SceneComponent, so cannot be parent: %s\n"),
*WingUtils::SanitizeName(FC.Name));
*WingUtils::ExternalizeID(FC.Name));
return false;
}
return true;
@@ -78,7 +78,7 @@ bool UWingComponentReference::CheckNoSuchComponent(FoundComponent FC)
if (FC.SCS || FC.Native)
{
UWingServer::Printf(TEXT("A component named %s already exists"),
*WingUtils::SanitizeName(FC.Name));
*WingUtils::ExternalizeID(FC.Name));
return false;
}
return true;
@@ -89,7 +89,7 @@ bool UWingComponentReference::CheckNotNative(FoundComponent FC, const TCHAR *Act
if (FC.Native != nullptr)
{
UWingServer::Printf(TEXT("Component %s is native, cannot %s native components"),
*WingUtils::SanitizeName(FC.Name), Action);
*WingUtils::ExternalizeID(FC.Name), Action);
return false;
}
return true;
@@ -100,7 +100,7 @@ bool UWingComponentReference::CheckOwnedByBlueprint(FoundComponent FC, UBlueprin
if ((FC.SCS == nullptr) || (FC.SCS->GetSCS() != BP->SimpleConstructionScript))
{
UWingServer::Printf(TEXT("Component %s belongs to blueprint %s, edit that blueprint instead"),
*WingUtils::SanitizeName(FC.Name), *WingUtils::FormatName(FC.SCS->GetSCS()->GetBlueprint()));
*WingUtils::ExternalizeID(FC.Name), *WingUtils::FormatName(FC.SCS->GetSCS()->GetBlueprint()));
return false;
}
return true;
@@ -151,7 +151,7 @@ bool UWingComponentReference::AddComponent(UBlueprint *BP, UClass *Class, UWingC
if (NewNode == nullptr)
{
UWingServer::Printf(TEXT("Could not create new component %s of class %s, unknown reason.\n"),
*WingUtils::SanitizeName(Name), *WingUtils::FormatName(Class));
*WingUtils::ExternalizeID(Name), *WingUtils::FormatName(Class));
return false;
}
@@ -262,7 +262,7 @@ TArray<UWingComponentReference*> UWingComponentReference::GetAll(UBlueprint* BP)
Ref->TypeName = UWingTypes::TypeToText(Comp->GetClass());
if (USceneComponent* Scene = Cast<USceneComponent>(Comp))
if (USceneComponent* AttachParent = Scene->GetAttachParent())
Ref->ParentName = WingUtils::SanitizeName(AttachParent->GetFName());
Ref->ParentName = WingUtils::ExternalizeID(AttachParent->GetFName());
Ref->Native = true;
Ref->Inherited = true;
Result.Add(Ref);
@@ -281,7 +281,7 @@ TArray<UWingComponentReference*> UWingComponentReference::GetAll(UBlueprint* BP)
Ref->BP = BP;
Ref->VariableName = Node->GetVariableName();
Ref->TypeName = UWingTypes::TypeToText(Node->ComponentClass);
Ref->ParentName = WingUtils::SanitizeName(ParentNames[Node->GetVariableName()]);
Ref->ParentName = WingUtils::ExternalizeID(ParentNames[Node->GetVariableName()]);
Ref->Native = false;
Ref->Inherited = (WalkBP != BP);
Result.Add(Ref);

View File

@@ -168,7 +168,7 @@ FString UWingTypes::NewShortName(const FString &Path, FName PinCategory, const U
if ((PinCategory == UEdGraphSchema_K2::PC_Object || PinCategory == UEdGraphSchema_K2::PC_Interface)
&& IsUserDefined && Proposal.EndsWith(TEXT("_C")))
Proposal.LeftChopInline(2);
Proposal = WingUtils::SanitizeName(Proposal);
Proposal = WingUtils::ExternalizeID(Proposal);
check(!Proposal.IsEmpty());
// Construct the Info struct.

View File

@@ -55,18 +55,12 @@
// Name sanitization
// ============================================================
FString WingUtils::SanitizeName(const FString &InName)
FString WingUtils::ExternalizeID(const FString &InName)
{
return WingTokenizer::ExternalizeID(InName);
}
FString WingUtils::UnsanitizeName(const FString &InName)
{
FString Error;
return WingTokenizer::TryInternalizeID(InName, Error);
}
FString WingUtils::SanitizeName(FName Name)
FString WingUtils::ExternalizeID(FName Name)
{
return WingTokenizer::ExternalizeID(Name.ToString());
}
@@ -111,7 +105,6 @@ FString WingUtils::StandardizeMenuItem(const FString &Item)
}
// ============================================================
// Name Lookup
// ============================================================
@@ -128,49 +121,49 @@ FString WingUtils::FormatName(const UBlueprint *BP)
FString WingUtils::FormatName(const UActorComponent *C)
{
return SanitizeName(C->GetName());
return ExternalizeID(C->GetName());
}
FString WingUtils::FormatName(const USCS_Node *Node)
{
return SanitizeName(Node->GetVariableName());
return ExternalizeID(Node->GetVariableName());
}
FString WingUtils::FormatName(const UEdGraph *Graph)
{
return SanitizeName(Graph->GetName());
return ExternalizeID(Graph->GetName());
}
FString WingUtils::FormatName(const TObjectPtr<UEdGraph> &Graph)
{
return SanitizeName(Graph->GetName());
return ExternalizeID(Graph->GetName());
}
FString WingUtils::FormatName(const UEdGraphNode* Node)
{
return SanitizeName(Node->GetName());
return ExternalizeID(Node->GetName());
}
FString WingUtils::FormatName(const UEdGraphPin *Pin)
{
return SanitizeName(Pin->GetName());
return ExternalizeID(Pin->GetName());
}
FString WingUtils::FormatName(const FMemberReference &Ref)
{
return SanitizeName(Ref.GetMemberName());
return ExternalizeID(Ref.GetMemberName());
}
FString WingUtils::FormatName(const FBPVariableDescription &Var)
{
return SanitizeName(Var.VarName);
return ExternalizeID(Var.VarName);
}
FString WingUtils::FormatName(const UStruct *Struct)
{
if (Cast<UScriptStruct>(Struct) || Cast<UClass>(Struct))
return UWingTypes::TypeToTextOrDie(Struct);
return SanitizeName(Struct->GetName());
return ExternalizeID(Struct->GetName());
}
FString WingUtils::FormatName(const UClass *Class)
@@ -195,7 +188,7 @@ FString WingUtils::FormatName(const UMaterialFunction *MaterialFunction)
FString WingUtils::FormatName(const UMaterialExpression *Expression)
{
return SanitizeName(Expression->GetName());
return ExternalizeID(Expression->GetName());
}
FString WingUtils::FormatName(const UStaticMesh *Mesh)
@@ -235,12 +228,12 @@ FString WingUtils::FormatName(const UEnum *Enum)
FString WingUtils::FormatName(const FProperty *Prop)
{
return SanitizeName(Prop->GetName());
return ExternalizeID(Prop->GetName());
}
FString WingUtils::FormatName(const FUserPinInfo &Pin)
{
return SanitizeName(Pin.PinName);
return ExternalizeID(Pin.PinName);
}
FString WingUtils::FormatName(const FBPInterfaceDescription &IFace)
@@ -250,12 +243,12 @@ FString WingUtils::FormatName(const FBPInterfaceDescription &IFace)
FString WingUtils::FormatName(const UWingComponentReference *Ref)
{
return SanitizeName(Ref->VariableName);
return ExternalizeID(Ref->VariableName);
}
FString WingUtils::FormatName(const UWidget *Widget)
{
return SanitizeName(Widget->GetName());
return ExternalizeID(Widget->GetName());
}
// ============================================================

View File

@@ -63,7 +63,7 @@ bool WingVariables::CheckSanity(Cat Category)
TSet<FName> NamesUsed;
for (const Var &Variable : Variables)
{
FString VarName = WingUtils::SanitizeName(Variable.Name);
FString VarName = WingUtils::ExternalizeID(Variable.Name);
FString TypeText = UWingTypes::TypeToText(Variable.Type);
if (NamesUsed.Contains(Variable.Name))
{
@@ -141,7 +141,7 @@ void WingVariables::PrintAll(FStringBuilderBase &Out, int32 Indent)
for (const Var& V : Variables)
{
FString TypeStr = UWingTypes::TypeToText(V.Type);
FString NameStr = WingUtils::SanitizeName(V.Name);
FString NameStr = WingUtils::ExternalizeID(V.Name);
// Build flags string.
FString FlagsStr;

View File

@@ -47,10 +47,8 @@ public:
//
// The goal here is to centralize the code that outputs
// names, and have everybody use it, so that names are
// used consistently. The secondary goal is to choose
// names that are as uniquely-identifying as is practical.
// It's not always 100% possible to get perfectly unique
// names, though, so our code needs to check for ambiguity.
// used consistently. When an identifier is output by
// FormatName, it's always an ExternalID.
//
////////////////////////////////////////////////////////
@@ -92,21 +90,12 @@ public:
////////////////////////////////////////////////////////
template<typename T>
static bool Identifies(const FString &Name, T&& Obj)
static bool Identifies(const FString &ExternalID, T&& Obj)
{
return FormatName(std::forward<T>(Obj)).Equals(Name, ESearchCase::IgnoreCase);
return FormatName(std::forward<T>(Obj)).Equals(ExternalID, ESearchCase::IgnoreCase);
}
////////////////////////////////////////////////////////
//
template<typename T>
static TArray<FString> FormatNames(const TArray<T> &Array)
{
TArray<FString> Result;
for (T& Elt : Array) Result.Add(FormatName(Elt));
return Result;
}
template<typename T>
static TArray<T*> FindAllNamed(const FString &Name, const TArray<T*> &Array)
@@ -155,16 +144,8 @@ public:
}
////////////////////////////////////////////////////////
////////////////////////////////////////////////////////
// Our parsers reserve certain punctuation marks for parsing
// types, paths, and the like. For example: Array<Int>.
// We therefore cannot allow those specific punctuation marks
// in names. We replace them with similar-looking unicode
// characters.
////////////////////////////////////////////////////////
static FString SanitizeName(const FString& Name);
static FString SanitizeName(FName Name);
static FString ExternalizeID(const FString& Name);
static FString ExternalizeID(FName Name);
////////////////////////////////////////////////////////
// In Unreal, Menu items tend to be an unpredictable
@@ -178,14 +159,13 @@ public:
////////////////////////////////////////////////////////
// This routine is used when the LLM is proposing a new
// name in order to create a new graph, new node, or
// something like that. This verifies that the name doesn't
// contain weird control characters that will confuse
// our name sanitization routines. If the name is valid,
// returns the *internal* name which should be stored in
// unreal's data structures. This is different than the
// name used by the LLM. If not valid, returns empty
// string.
// something like that. This verifies that the name is
// a valid external ID, it converts it to an internal ID,
// and it also verifies that it's a readable internal ID.
// If anything goes wrong, it prints an error and returns
// empty string.
////////////////////////////////////////////////////////
[[nodiscard]] static FString CheckProposedName(const FString &Name);
static FString FormatNodeTitle(const UEdGraphNode *Node);
@@ -240,8 +220,5 @@ public:
static bool CheckExactlyOneNamed(int Count, const TCHAR *Kind, const FString &Name);
static bool CheckExactlyNoneNamed(int Count, const TCHAR *Kind, const FString &Name);
static bool CheckCanRename(UEdGraphNode* Node, const FString &Name);
private:
static FString UnsanitizeName(const FString &Input);
};

0
tools/wing-rename.py Normal file → Executable file
View File