More work on name validation
This commit is contained in:
@@ -48,11 +48,9 @@ public:
|
||||
if (!BP) return;
|
||||
|
||||
// Check that the proposed name is valid
|
||||
FName InternalID = WingUtils::CheckProposedName(Component, WingOut::Stdout);
|
||||
TSet<FName> InUse = WingUtils::GetAllInUseNames(BP);
|
||||
FName InternalID = WingUtils::CheckProposedName(Component, InUse, WingOut::Stdout);
|
||||
if (InternalID.IsNone()) return;
|
||||
TSet<FName> Names;
|
||||
WingUtils::GetAllInUseNames(BP, Names);
|
||||
if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("variable or component"), WingOut::Stdout)) return;
|
||||
|
||||
// Resolve the component class by name
|
||||
UWingTypes::Requirements Req;
|
||||
|
||||
@@ -73,11 +73,9 @@ public:
|
||||
}
|
||||
|
||||
// Check graph name uniqueness and legality
|
||||
FName InternalID = WingUtils::CheckProposedName(Graph, WingOut::Stdout);
|
||||
TSet<FName> InUse = WingUtils::GetAllInUseNames(BP);
|
||||
FName InternalID = WingUtils::CheckProposedName(Graph, InUse, WingOut::Stdout);
|
||||
if (InternalID.IsNone()) return;
|
||||
TSet<FName> Names;
|
||||
if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("Graph"), WingOut::Stdout)) return;
|
||||
if (!WingUtils::FindNoDuplicateNames(Names, WingUtils::AllGraphs(BP), TEXT("Graph"), WingOut::Stdout)) return;
|
||||
|
||||
// Parse and validate variables before making changes
|
||||
WingVariables Vars;
|
||||
|
||||
@@ -43,11 +43,9 @@ public:
|
||||
if (!BP) return;
|
||||
|
||||
// Check for valid proposed name
|
||||
FName InternalID = WingUtils::CheckProposedName(Dispatcher, WingOut::Stdout);
|
||||
TSet<FName> InUse = WingUtils::GetAllInUseNames(BP);
|
||||
FName InternalID = WingUtils::CheckProposedName(Dispatcher, InUse, WingOut::Stdout);
|
||||
if (InternalID.IsNone()) return;
|
||||
TSet<FName> Names;
|
||||
WingUtils::GetAllInUseNames(BP, Names);
|
||||
if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("variable or component"), WingOut::Stdout)) return;
|
||||
|
||||
// Parse the arguments.
|
||||
WingVariables Vars;
|
||||
|
||||
@@ -66,14 +66,10 @@ public:
|
||||
}
|
||||
|
||||
// Validate the proposed name.
|
||||
FName InternalID = WingUtils::CheckProposedName(Name, WingOut::Stdout);
|
||||
TSet<FName> InUse = WingUtils::GetAllInUseNames(BP);
|
||||
FName InternalID = WingUtils::CheckProposedName(Name, InUse, WingOut::Stdout);
|
||||
if (InternalID.IsNone()) return;
|
||||
|
||||
// Check that the name is unique among existing widgets.
|
||||
TSet<FName> Names;
|
||||
WingUtils::GetAllInUseNames(BP, Names);
|
||||
if (!WingUtils::FindNoDuplicateName(Names, InternalID, TEXT("widget or variable"), WingOut::Stdout)) return;
|
||||
|
||||
// If a parent is specified, find it and verify it's a panel.
|
||||
UPanelWidget* ParentPanel = nullptr;
|
||||
TArray<UWidget*> AllWidgets;
|
||||
|
||||
@@ -149,8 +149,7 @@ bool UWingComponent::AddComponent(UBlueprint *BP, UClass *Class, UWingComponentR
|
||||
Errors.Printf(TEXT("This blueprint cannot contain components.\n"));
|
||||
return false;
|
||||
}
|
||||
TSet<FName> Names;
|
||||
WingUtils::GetAllInUseNames(BP, Names);
|
||||
TSet<FName> Names = WingUtils::GetAllInUseNames(BP);
|
||||
if (Names.Contains(Name))
|
||||
{
|
||||
Errors.Printf(TEXT("There is already a variable or component named %s in %s.\n"),
|
||||
|
||||
@@ -61,7 +61,7 @@ FName WingUtils::CheckInternalizeID(const FString &ExternalID, WingOut Errors)
|
||||
return InternalID;
|
||||
}
|
||||
|
||||
FName WingUtils::CheckProposedName(const FString &ExternalID, WingOut Errors)
|
||||
FName WingUtils::CheckProposedName(const FString &ExternalID, const TSet<FName> &InUse, WingOut Errors)
|
||||
{
|
||||
FName InternalID = CheckInternalizeID(ExternalID, Errors);
|
||||
if (InternalID.ToString().Len() > 100)
|
||||
@@ -76,6 +76,11 @@ FName WingUtils::CheckProposedName(const FString &ExternalID, WingOut Errors)
|
||||
UWingServer::SuggestManual(WingManual::Section::EscapeSequences);
|
||||
return FName();
|
||||
}
|
||||
if (InUse.Contains(InternalID))
|
||||
{
|
||||
Errors.Printf(TEXT("ERROR: id %s is already in use"), *ExternalID);
|
||||
return FName();
|
||||
}
|
||||
return InternalID;
|
||||
}
|
||||
|
||||
@@ -483,8 +488,9 @@ UObject *WingUtils::GetGeneratedCDO(UBlueprint *BP)
|
||||
return BP->GeneratedClass->GetDefaultObject();
|
||||
}
|
||||
|
||||
void WingUtils::GetAllInUseNames(UBlueprint *BP, TSet<FName> &Names)
|
||||
TSet<FName> WingUtils::GetAllInUseNames(UBlueprint *BP)
|
||||
{
|
||||
TSet<FName> Names;
|
||||
FBlueprintEditorUtils::GetClassVariableList(BP, Names, true);
|
||||
FBlueprintEditorUtils::GetFunctionNameList(BP, Names);
|
||||
FBlueprintEditorUtils::GetAllGraphNames(BP, Names);
|
||||
@@ -496,6 +502,7 @@ void WingUtils::GetAllInUseNames(UBlueprint *BP, TSet<FName> &Names)
|
||||
WBP->WidgetTree->GetAllWidgets(AllWidgets);
|
||||
WingUtils::AddNamesToSet(Names, AllWidgets);
|
||||
}
|
||||
return Names;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
|
||||
@@ -611,9 +611,8 @@ bool WingVariables::CreateBlueprint(WingOut Errors)
|
||||
ClearLinks();
|
||||
|
||||
// Check for name collisions against existing variables, components, and the like.
|
||||
TSet<FName> Names;
|
||||
WingUtils::GetAllInUseNames(Blueprint.Get(), Names);
|
||||
if (!WingUtils::FindNoDuplicateNames(Names, BlueprintVariables.Variables, TEXT("variable or component"), Errors)) return false;
|
||||
TSet<FName> InUse = WingUtils::GetAllInUseNames(Blueprint.Get());
|
||||
if (!WingUtils::FindNoDuplicateNames(InUse, BlueprintVariables.Variables, TEXT("variable or component"), Errors)) return false;
|
||||
|
||||
// Create the variables.
|
||||
for (const WingVariables::Var& V : BlueprintVariables.Variables)
|
||||
|
||||
@@ -218,13 +218,14 @@ 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 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.
|
||||
// a valid external ID, it converts it to an internal
|
||||
// ID, and it also verifies that it's a readable
|
||||
// internal ID, and that it is not already in use.
|
||||
// If anything goes wrong, it prints an error and
|
||||
// returns empty string.
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
static FName CheckProposedName(const FString &Name, WingOut Errors);
|
||||
static FName CheckProposedName(const FString &Name, const TSet<FName> &InUse, WingOut Errors);
|
||||
|
||||
static FString FormatNodeTitle(const UEdGraphNode *Node);
|
||||
|
||||
@@ -250,7 +251,7 @@ public:
|
||||
static TArray<UEdGraphNode*> AllNodes(UEdGraph *Graph);
|
||||
static TArray<UBlueprint*> GetAncestorBlueprints(UBlueprint *BP, bool OldestFirst = false);
|
||||
static UObject *GetGeneratedCDO(UBlueprint *BP);
|
||||
static void GetAllInUseNames(UBlueprint *BP, TSet<FName> &Names);
|
||||
static TSet<FName> GetAllInUseNames(UBlueprint *BP);
|
||||
|
||||
// ----- Graph pin helpers -----
|
||||
static UEdGraphPin* CheckGetPin(UEdGraphNode* Node, FName PinName, WingOut Errors);
|
||||
|
||||
Reference in New Issue
Block a user