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