560 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			560 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								// Tencent is pleased to support the open source community by making UnLua available.
							 | 
						|||
| 
								 | 
							
								// 
							 | 
						|||
| 
								 | 
							
								// Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
							 | 
						|||
| 
								 | 
							
								//
							 | 
						|||
| 
								 | 
							
								// Licensed under the MIT License (the "License"); 
							 | 
						|||
| 
								 | 
							
								// you may not use this file except in compliance with the License. You may obtain a copy of the License at
							 | 
						|||
| 
								 | 
							
								//
							 | 
						|||
| 
								 | 
							
								// http://opensource.org/licenses/MIT
							 | 
						|||
| 
								 | 
							
								//
							 | 
						|||
| 
								 | 
							
								// Unless required by applicable law or agreed to in writing, 
							 | 
						|||
| 
								 | 
							
								// software distributed under the License is distributed on an "AS IS" BASIS, 
							 | 
						|||
| 
								 | 
							
								// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
							 | 
						|||
| 
								 | 
							
								// See the License for the specific language governing permissions and limitations under the License.
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#include "UnLuaIntelliSense.h"
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#include "Binding.h"
							 | 
						|||
| 
								 | 
							
								#include "ObjectEditorUtils.h"
							 | 
						|||
| 
								 | 
							
								#include "UnLuaInterface.h"
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								namespace UnLua
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								    namespace IntelliSense
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        static const FName NAME_ToolTip(TEXT("ToolTip")); // key of ToolTip meta data
							 | 
						|||
| 
								 | 
							
								        static const FName NAME_LatentInfo = TEXT("LatentInfo"); // tag of latent function
							 | 
						|||
| 
								 | 
							
								        static FString LuaKeywords[] = {TEXT("local"), TEXT("function"), TEXT("end")};
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        static FString GetCommentBlock(const UField* Field)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            const FString ToolTip = Field->GetMetaData(NAME_ToolTip);
							 | 
						|||
| 
								 | 
							
								            if (ToolTip.IsEmpty())
							 | 
						|||
| 
								 | 
							
								                return "";
							 | 
						|||
| 
								 | 
							
								            return "---" + EscapeComments(ToolTip, false) + "\r\n";
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FString Get(const UBlueprint* Blueprint)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            return Get(Blueprint->GeneratedClass);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FString Get(const UField* Field)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            const UStruct* Struct = Cast<UStruct>(Field);
							 | 
						|||
| 
								 | 
							
								            if (Struct)
							 | 
						|||
| 
								 | 
							
								                return Get(Struct);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            const UEnum* Enum = Cast<UEnum>(Field);
							 | 
						|||
| 
								 | 
							
								            if (Enum)
							 | 
						|||
| 
								 | 
							
								                return Get(Enum);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return "";
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FString Get(const UEnum* Enum)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            FString Ret = GetCommentBlock(Enum);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            FString TypeName = GetTypeName(Enum);
							 | 
						|||
| 
								 | 
							
								            Ret += FString::Printf(TEXT("---@class %s"), *TypeName);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // fields
							 | 
						|||
| 
								 | 
							
								            const int32 Num = Enum->NumEnums();
							 | 
						|||
| 
								 | 
							
								            for (int32 i = 0; i < Num; ++i)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                Ret += FString::Printf(TEXT("\r\n---@field %s %s %s"), TEXT("public"), *Enum->GetNameStringByIndex(i), TEXT("integer"));
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // declaration
							 | 
						|||
| 
								 | 
							
								            Ret += FString::Printf(TEXT("\r\nlocal %s = {}\r\n"), *EscapeSymbolName(TypeName));
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return Ret;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FString Get(const UStruct* Struct)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            const UClass* Class = Cast<UClass>(Struct);
							 | 
						|||
| 
								 | 
							
								            if (Class)
							 | 
						|||
| 
								 | 
							
								                return Get(Class);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            const UScriptStruct* ScriptStruct = Cast<UScriptStruct>(Struct);
							 | 
						|||
| 
								 | 
							
								            if (ScriptStruct)
							 | 
						|||
| 
								 | 
							
								                return Get(ScriptStruct);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            const UFunction* Function = Cast<UFunction>(Struct);
							 | 
						|||
| 
								 | 
							
								            if (Function)
							 | 
						|||
| 
								 | 
							
								                return Get(Function);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return "";
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FString Get(const UScriptStruct* ScriptStruct)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            FString Ret = GetCommentBlock(ScriptStruct);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            FString TypeName = GetTypeName(ScriptStruct);
							 | 
						|||
| 
								 | 
							
								            Ret += "---@class " + TypeName;
							 | 
						|||
| 
								 | 
							
								            UStruct* SuperStruct = ScriptStruct->GetSuperStruct();
							 | 
						|||
| 
								 | 
							
								            if (SuperStruct)
							 | 
						|||
| 
								 | 
							
								                Ret += " : " + GetTypeName(SuperStruct);
							 | 
						|||
| 
								 | 
							
								            Ret += "\r\n";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // fields
							 | 
						|||
| 
								 | 
							
								            for (TFieldIterator<FProperty> It(ScriptStruct, EFieldIteratorFlags::ExcludeSuper, EFieldIteratorFlags::ExcludeDeprecated); It; ++It)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const FProperty* Property = *It;
							 | 
						|||
| 
								 | 
							
								                Ret += Get(Property) += "\r\n";
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // declaration
							 | 
						|||
| 
								 | 
							
								            Ret += FString::Printf(TEXT("local %s = {}\r\n"), *EscapeSymbolName(TypeName));
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // exported functions
							 | 
						|||
| 
								 | 
							
								            const auto Exported = GetExportedReflectedClasses().Find(TypeName);
							 | 
						|||
| 
								 | 
							
								            if (Exported)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                TArray<IExportedFunction*> ExportedFunctions;
							 | 
						|||
| 
								 | 
							
								                (*Exported)->GetFunctions(ExportedFunctions);
							 | 
						|||
| 
								 | 
							
								                for (const auto Function : ExportedFunctions)
							 | 
						|||
| 
								 | 
							
								                    Function->GenerateIntelliSense(Ret);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            return Ret;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FString Get(const UClass* Class)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            FString Ret = GetCommentBlock(Class);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            const FString TypeName = GetTypeName(Class);
							 | 
						|||
| 
								 | 
							
								            Ret += "---@class " + TypeName;
							 | 
						|||
| 
								 | 
							
								            UStruct* SuperStruct = Class->GetSuperStruct();
							 | 
						|||
| 
								 | 
							
								            if (SuperStruct)
							 | 
						|||
| 
								 | 
							
								                Ret += " : " + GetTypeName(SuperStruct);
							 | 
						|||
| 
								 | 
							
								            Ret += "\r\n";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // fields
							 | 
						|||
| 
								 | 
							
								            for (TFieldIterator<FProperty> It(Class, EFieldIteratorFlags::ExcludeSuper, EFieldIteratorFlags::ExcludeDeprecated); It; ++It)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const FProperty* Property = *It;
							 | 
						|||
| 
								 | 
							
								                Ret += Get(Property) += "\r\n";
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // declaration
							 | 
						|||
| 
								 | 
							
								            const auto EscapedClassName = EscapeSymbolName(TypeName);
							 | 
						|||
| 
								 | 
							
								            Ret += FString::Printf(TEXT("local %s = {}\r\n\r\n"), *EscapedClassName);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            TArray<FString> GenFunctionNames;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // functions
							 | 
						|||
| 
								 | 
							
								            for (TFieldIterator<UFunction> FunctionIt(Class, EFieldIteratorFlags::ExcludeSuper, EFieldIteratorFlags::ExcludeDeprecated, EFieldIteratorFlags::ExcludeInterfaces); FunctionIt; ++FunctionIt)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const UFunction* Function = *FunctionIt;
							 | 
						|||
| 
								 | 
							
								                if (!IsValid(Function))
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								                if (FObjectEditorUtils::IsFunctionHiddenFromClass(Function, Class))
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								                Ret += Get(Function) + "\r\n";
							 | 
						|||
| 
								 | 
							
								                GenFunctionNames.Add(Function->GetName());
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // interface functions
							 | 
						|||
| 
								 | 
							
								            for (TFieldIterator<UFunction> FunctionIt(Class, EFieldIteratorFlags::IncludeSuper, EFieldIteratorFlags::ExcludeDeprecated, EFieldIteratorFlags::IncludeInterfaces); FunctionIt; ++FunctionIt)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const UFunction* Function = *FunctionIt;
							 | 
						|||
| 
								 | 
							
								                if (!Function->GetOwnerClass()->IsChildOf(UInterface::StaticClass()))
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								                if (!IsValid(Function))
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								                if (FObjectEditorUtils::IsFunctionHiddenFromClass(Function, Class))
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								                if (GenFunctionNames.Contains(Function->GetName()))
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								                Ret += Get(Function, EscapedClassName) + "\r\n";
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // exported functions
							 | 
						|||
| 
								 | 
							
								            const auto Exported = GetExportedReflectedClasses().Find(TypeName);
							 | 
						|||
| 
								 | 
							
								            if (Exported)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                TArray<IExportedFunction*> ExportedFunctions;
							 | 
						|||
| 
								 | 
							
								                (*Exported)->GetFunctions(ExportedFunctions);
							 | 
						|||
| 
								 | 
							
								                for (const auto Function : ExportedFunctions)
							 | 
						|||
| 
								 | 
							
								                    Function->GenerateIntelliSense(Ret);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            return Ret;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FString Get(const UFunction* Function, FString ForceClassName)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            FString Ret = GetCommentBlock(Function);
							 | 
						|||
| 
								 | 
							
								            FString Properties;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            for (TFieldIterator<FProperty> It(Function); It && (It->PropertyFlags & CPF_Parm); ++It)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const FProperty* Property = *It;
							 | 
						|||
| 
								 | 
							
								                if (Property->GetFName() == NAME_LatentInfo)
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                FString TypeName = EscapeSymbolName(GetTypeName(Property));
							 | 
						|||
| 
								 | 
							
								                const FString& PropertyComment = Property->GetMetaData(NAME_ToolTip);
							 | 
						|||
| 
								 | 
							
								                FString ExtraDesc;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (Property->HasAnyPropertyFlags(CPF_ReturnParm))
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    Ret += FString::Printf(TEXT("---@return %s"), *TypeName); // return parameter
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								                else
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    FString PropertyName = EscapeSymbolName(*Property->GetName());
							 | 
						|||
| 
								 | 
							
								                    if (Properties.IsEmpty())
							 | 
						|||
| 
								 | 
							
								                        Properties = PropertyName;
							 | 
						|||
| 
								 | 
							
								                    else
							 | 
						|||
| 
								 | 
							
								                        Properties += FString::Printf(TEXT(", %s"), *PropertyName);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                    FName KeyName = FName(*FString::Printf(TEXT("CPP_Default_%s"), *Property->GetName()));
							 | 
						|||
| 
								 | 
							
								                    const FString& Value = Function->GetMetaData(KeyName);
							 | 
						|||
| 
								 | 
							
								                    if (!Value.IsEmpty())
							 | 
						|||
| 
								 | 
							
								                    {
							 | 
						|||
| 
								 | 
							
								                        ExtraDesc = TEXT("[opt]"); // default parameter
							 | 
						|||
| 
								 | 
							
								                    }
							 | 
						|||
| 
								 | 
							
								                    else if (Property->HasAnyPropertyFlags(CPF_OutParm) && !Property->HasAnyPropertyFlags(CPF_ConstParm))
							 | 
						|||
| 
								 | 
							
								                    {
							 | 
						|||
| 
								 | 
							
								                        ExtraDesc = TEXT("[out]"); // non-const reference
							 | 
						|||
| 
								 | 
							
								                    }
							 | 
						|||
| 
								 | 
							
								                    Ret += FString::Printf(TEXT("---@param %s %s"), *PropertyName, *TypeName);
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                if (ExtraDesc.Len() > 0 || PropertyComment.Len() > 0)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    Ret += TEXT(" @");
							 | 
						|||
| 
								 | 
							
								                    if (ExtraDesc.Len() > 0)
							 | 
						|||
| 
								 | 
							
								                        Ret += FString::Printf(TEXT("%s "), *ExtraDesc);
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                Ret += TEXT("\r\n");
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            const auto ClassName = ForceClassName.IsEmpty() ? EscapeSymbolName(GetTypeName(Function->GetOwnerClass())) : ForceClassName;
							 | 
						|||
| 
								 | 
							
								            const auto FunctionName = Function->GetName();
							 | 
						|||
| 
								 | 
							
								            const auto bIsStatic = Function->HasAnyFunctionFlags(FUNC_Static);
							 | 
						|||
| 
								 | 
							
								            if (IsValidFunctionName(FunctionName))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                Ret += FString::Printf(TEXT("function %s%s%s(%s) end\r\n"), *ClassName, bIsStatic ? TEXT(".") : TEXT(":"), *FunctionName, *Properties);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            else
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const auto Self = bIsStatic ? TEXT("") : TEXT("self");
							 | 
						|||
| 
								 | 
							
								                const auto Comma = bIsStatic || Properties.IsEmpty() ? TEXT("") : TEXT(", ");
							 | 
						|||
| 
								 | 
							
								                Ret += FString::Printf(TEXT("%s[\"%s\"] = function(%s%s%s) end\r\n"), *ClassName, *FunctionName, Self, Comma, *Properties);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            return Ret;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FString Get(const FProperty* Property)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            FString Ret;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            const UStruct* Struct = Property->GetOwnerStruct();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // access level
							 | 
						|||
| 
								 | 
							
								            FString AccessLevel;
							 | 
						|||
| 
								 | 
							
								            if (Property->HasAnyPropertyFlags(CPF_NativeAccessSpecifierPublic))
							 | 
						|||
| 
								 | 
							
								                AccessLevel = TEXT("public");
							 | 
						|||
| 
								 | 
							
								            else if (Property->HasAllPropertyFlags(CPF_NativeAccessSpecifierProtected))
							 | 
						|||
| 
								 | 
							
								                AccessLevel = TEXT("protected");
							 | 
						|||
| 
								 | 
							
								            else if (Property->HasAllPropertyFlags(CPF_NativeAccessSpecifierPrivate))
							 | 
						|||
| 
								 | 
							
								                AccessLevel = TEXT("private");
							 | 
						|||
| 
								 | 
							
								            else
							 | 
						|||
| 
								 | 
							
								                AccessLevel = Struct->IsNative() ? "private" : "public";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            FString TypeName = IntelliSense::GetTypeName(Property);
							 | 
						|||
| 
								 | 
							
								            Ret += FString::Printf(TEXT("---@field %s %s %s"), *AccessLevel, *Property->GetName(), *TypeName);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // comment
							 | 
						|||
| 
								 | 
							
								            const FString& ToolTip = Property->GetMetaData(NAME_ToolTip);
							 | 
						|||
| 
								 | 
							
								            if (!ToolTip.IsEmpty())
							 | 
						|||
| 
								 | 
							
								                Ret += " @" + EscapeComments(ToolTip, true);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return Ret;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FString GetUE(const TArray<const UField*> AllTypes)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            FString Content = "UE = {";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            for (const auto Type : AllTypes)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (!Type->IsNative())
							 | 
						|||
| 
								 | 
							
								                    continue;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								                const auto Name = GetTypeName(Type);
							 | 
						|||
| 
								 | 
							
								                Content += FString::Printf(TEXT("\r\n    ---@type %s\r\n"), *Name);
							 | 
						|||
| 
								 | 
							
								                Content += FString::Printf(TEXT("    %s = nil,\r\n"), *Name);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            Content += "}\r\n";
							 | 
						|||
| 
								 | 
							
								            return Content;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FString GetTypeName(const UObject* Field)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (!Field)
							 | 
						|||
| 
								 | 
							
								                return "";
							 | 
						|||
| 
								 | 
							
								            if (!Field->IsNative() && Field->GetName().EndsWith("_C"))
							 | 
						|||
| 
								 | 
							
								                return Field->GetName();
							 | 
						|||
| 
								 | 
							
								            const UStruct* Struct = Cast<UStruct>(Field);
							 | 
						|||
| 
								 | 
							
								            if (Struct)
							 | 
						|||
| 
								 | 
							
								                return Struct->GetPrefixCPP() + Struct->GetName();
							 | 
						|||
| 
								 | 
							
								            return Field->GetName();
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FString GetTypeName(const FProperty* Property)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (!Property)
							 | 
						|||
| 
								 | 
							
								                return "Unknown";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FByteProperty>(Property))
							 | 
						|||
| 
								 | 
							
								                return "integer";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FInt8Property>(Property))
							 | 
						|||
| 
								 | 
							
								                return "integer";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FInt16Property>(Property))
							 | 
						|||
| 
								 | 
							
								                return "integer";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FIntProperty>(Property))
							 | 
						|||
| 
								 | 
							
								                return "integer";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FInt64Property>(Property))
							 | 
						|||
| 
								 | 
							
								                return "integer";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FUInt16Property>(Property))
							 | 
						|||
| 
								 | 
							
								                return "integer";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FUInt32Property>(Property))
							 | 
						|||
| 
								 | 
							
								                return "integer";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FUInt64Property>(Property))
							 | 
						|||
| 
								 | 
							
								                return "integer";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FFloatProperty>(Property))
							 | 
						|||
| 
								 | 
							
								                return "number";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FDoubleProperty>(Property))
							 | 
						|||
| 
								 | 
							
								                return "number";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FEnumProperty>(Property))
							 | 
						|||
| 
								 | 
							
								                return ((FEnumProperty*)Property)->GetEnum()->GetName();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FBoolProperty>(Property))
							 | 
						|||
| 
								 | 
							
								                return TEXT("boolean");
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FClassProperty>(Property))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const UClass* Class = ((FClassProperty*)Property)->MetaClass;
							 | 
						|||
| 
								 | 
							
								                return FString::Printf(TEXT("TSubclassOf<%s%s>"), Class->GetPrefixCPP(), *Class->GetName());
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FSoftObjectProperty>(Property))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (((FSoftObjectProperty*)Property)->PropertyClass->IsChildOf(UClass::StaticClass()))
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    const UClass* Class = ((FSoftClassProperty*)Property)->MetaClass;
							 | 
						|||
| 
								 | 
							
								                    return FString::Printf(TEXT("TSoftClassPtr<%s%s>"), Class->GetPrefixCPP(), *Class->GetName());
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								                const UClass* Class = ((FSoftObjectProperty*)Property)->PropertyClass;
							 | 
						|||
| 
								 | 
							
								                return FString::Printf(TEXT("TSoftObjectPtr<%s%s>"), Class->GetPrefixCPP(), *Class->GetName());
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FObjectProperty>(Property))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const UClass* Class = ((FObjectProperty*)Property)->PropertyClass;
							 | 
						|||
| 
								 | 
							
								                if (Cast<UBlueprintGeneratedClass>(Class))
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    return FString::Printf(TEXT("%s"), *Class->GetName());
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								                return FString::Printf(TEXT("%s%s"), Class->GetPrefixCPP(), *Class->GetName());
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FWeakObjectProperty>(Property))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const UClass* Class = ((FWeakObjectProperty*)Property)->PropertyClass;
							 | 
						|||
| 
								 | 
							
								                return FString::Printf(TEXT("TWeakObjectPtr<%s%s>"), Class->GetPrefixCPP(), *Class->GetName());
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FLazyObjectProperty>(Property))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const UClass* Class = ((FLazyObjectProperty*)Property)->PropertyClass;
							 | 
						|||
| 
								 | 
							
								                return FString::Printf(TEXT("TLazyObjectPtr<%s%s>"), Class->GetPrefixCPP(), *Class->GetName());
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FInterfaceProperty>(Property))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const UClass* Class = ((FInterfaceProperty*)Property)->InterfaceClass;
							 | 
						|||
| 
								 | 
							
								                return FString::Printf(TEXT("TScriptInterface<%s%s>"), Class->GetPrefixCPP(), *Class->GetName());
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FNameProperty>(Property))
							 | 
						|||
| 
								 | 
							
								                return "string";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FStrProperty>(Property))
							 | 
						|||
| 
								 | 
							
								                return "string";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FTextProperty>(Property))
							 | 
						|||
| 
								 | 
							
								                return "string";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FArrayProperty>(Property))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const FProperty* Inner = ((FArrayProperty*)Property)->Inner;
							 | 
						|||
| 
								 | 
							
								                return FString::Printf(TEXT("TArray<%s>"), *GetTypeName(Inner));
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FMapProperty>(Property))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const FProperty* KeyProp = ((FMapProperty*)Property)->KeyProp;
							 | 
						|||
| 
								 | 
							
								                const FProperty* ValueProp = ((FMapProperty*)Property)->ValueProp;
							 | 
						|||
| 
								 | 
							
								                return FString::Printf(TEXT("TMap<%s, %s>"), *GetTypeName(KeyProp), *GetTypeName(ValueProp));
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FSetProperty>(Property))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const FProperty* ElementProp = ((FSetProperty*)Property)->ElementProp;
							 | 
						|||
| 
								 | 
							
								                return FString::Printf(TEXT("TSet<%s>"), *GetTypeName(ElementProp));
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FStructProperty>(Property))
							 | 
						|||
| 
								 | 
							
								                return ((FStructProperty*)Property)->Struct->GetStructCPPName();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FDelegateProperty>(Property))
							 | 
						|||
| 
								 | 
							
								                return "Delegate";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (CastField<FMulticastDelegateProperty>(Property))
							 | 
						|||
| 
								 | 
							
								                return "MulticastDelegate";
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return "Unknown";
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FString EscapeComments(const FString Comments, const bool bSingleLine)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (Comments.IsEmpty())
							 | 
						|||
| 
								 | 
							
								                return Comments;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            auto Filter = [](const FString Prefix, const FString Line)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (Line.StartsWith("@"))
							 | 
						|||
| 
								 | 
							
								                    return FString();
							 | 
						|||
| 
								 | 
							
								                return Prefix + Line;
							 | 
						|||
| 
								 | 
							
								            };
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            TArray<FString> Lines;
							 | 
						|||
| 
								 | 
							
								            Comments.Replace(TEXT("@"), TEXT("@@")).ParseIntoArray(Lines, TEXT("\n"));
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            FString Ret = Filter("", Lines[0]);
							 | 
						|||
| 
								 | 
							
								            if (bSingleLine)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                for (int i = 1; i < Lines.Num(); i++)
							 | 
						|||
| 
								 | 
							
								                    Ret += Filter(" ", Lines[i]);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            else
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                for (int i = 1; i < Lines.Num(); i++)
							 | 
						|||
| 
								 | 
							
								                    Ret += Filter("\r\n---", Lines[i]);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return Ret;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        FString EscapeSymbolName(const FString InName)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            FString Name = InName;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // 和Lua关键字重名就加前缀
							 | 
						|||
| 
								 | 
							
								            for (const auto& Keyword : LuaKeywords)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (Name.Equals(Keyword, ESearchCase::CaseSensitive))
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    Name = TEXT("_") + Name;
							 | 
						|||
| 
								 | 
							
								                    break;
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // 替换掉除中文外的特殊字符
							 | 
						|||
| 
								 | 
							
								            for (int32 Index = 0; Index < Name.Len(); Index++)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                const auto Char = Name[Index];
							 | 
						|||
| 
								 | 
							
								                if ((Char < '0' || Char > '9')
							 | 
						|||
| 
								 | 
							
								                    && (Char < 'a' || Char > 'z')
							 | 
						|||
| 
								 | 
							
								                    && (Char < 'A' || Char > 'Z')
							 | 
						|||
| 
								 | 
							
								                    && Char != '_'
							 | 
						|||
| 
								 | 
							
								                    && Char < 0x100)
							 | 
						|||
| 
								 | 
							
								                {
							 | 
						|||
| 
								 | 
							
								                    Name[Index] = TCHAR('_');
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // 数字开头就加前缀
							 | 
						|||
| 
								 | 
							
								            const auto PrefixChar = Name[0];
							 | 
						|||
| 
								 | 
							
								            if (PrefixChar >= '0' && PrefixChar <= '9')
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                Name = TEXT("_") + Name;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return Name;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        bool IsValid(const UFunction* Function)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (!Function)
							 | 
						|||
| 
								 | 
							
								                return false;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (Function->HasAnyFunctionFlags(FUNC_UbergraphFunction))
							 | 
						|||
| 
								 | 
							
								                return false;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // 这个会导致USubsystemBlueprintLibrary.GetWorldSubsystem之类的被过滤掉
							 | 
						|||
| 
								 | 
							
								            // if (!UEdGraphSchema_K2::CanUserKismetCallFunction(Function))
							 | 
						|||
| 
								 | 
							
								            //     return false;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            const FString Name = Function->GetName();
							 | 
						|||
| 
								 | 
							
								            if (Name.IsEmpty())
							 | 
						|||
| 
								 | 
							
								                return false;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // 避免运行时生成智能提示,把覆写的函数也生成了
							 | 
						|||
| 
								 | 
							
								            if (Name.EndsWith("__Overridden"))
							 | 
						|||
| 
								 | 
							
								                return false;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return true;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        bool IsValidFunctionName(const FString Name)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            if (Name.IsEmpty())
							 | 
						|||
| 
								 | 
							
								                return false;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // 不能有Lua关键字
							 | 
						|||
| 
								 | 
							
								            for (const auto& Keyword : LuaKeywords)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if (Name.Equals(Keyword, ESearchCase::CaseSensitive))
							 | 
						|||
| 
								 | 
							
								                    return false;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // 不能有中文和特殊字符
							 | 
						|||
| 
								 | 
							
								            for (const auto& Char : Name)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                if ((Char < '0' || Char > '9')
							 | 
						|||
| 
								 | 
							
								                    && (Char < 'a' || Char > 'z')
							 | 
						|||
| 
								 | 
							
								                    && (Char < 'A' || Char > 'Z')
							 | 
						|||
| 
								 | 
							
								                    && Char != '_')
							 | 
						|||
| 
								 | 
							
								                    return false;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            // 不能以数字开头
							 | 
						|||
| 
								 | 
							
								            const auto& PrefixChar = Name[0];
							 | 
						|||
| 
								 | 
							
								            if (PrefixChar >= '0' && PrefixChar <= '9')
							 | 
						|||
| 
								 | 
							
								                return false;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            return true;
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 |