Files
JJBB/Assets/XLua/Src/Editor/Template/TemplateCommon.lua.txt

472 lines
18 KiB
Plaintext

-- Tencent is pleased to support the open source community by making xLua available.
-- Copyright (C) 2016 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.
local friendlyNameMap = {
["System.Object"] = "object",
["System.String"] = "string",
["System.Boolean"] = "bool",
["System.Byte"] = "byte",
["System.Char"] = "char",
["System.Decimal"] = "decimal",
["System.Double"] = "double",
["System.Int16"] = "short",
["System.Int32"] = "int",
["System.Int64"] = "long",
["System.SByte"] = "sbyte",
["System.Single"] = "float",
["System.UInt16"] = "ushort",
["System.UInt32"] = "uint",
["System.UInt64"] = "ulong",
["System.Void"] = "void",
}
local csKeywords = {
"abstract", "as", "base", "bool",
"break", "byte", "case", "catch",
"char", "checked", "class", "const",
"continue", "decimal", "default", "delegate",
"do", "double", "else", "enum",
"event", "explicit", "extern", "false",
"finally", "fixed", "float", "for",
"foreach", "goto", "if", "implicit",
"in", "int", "interface",
"internal", "is", "lock", "long",
"namespace", "new", "null", "object",
"operator", "out", "override",
"params", "private", "protected", "public",
"readonly", "ref", "return", "sbyte",
"sealed", "short", "sizeof", "stackalloc",
"static", "string", "struct", "switch",
"this", "throw", "true", "try",
"typeof", "uint", "ulong", "unchecked",
"unsafe", "ushort", "using", "virtual",
"void", "volatile", "while"
}
for _, kw in ipairs(csKeywords) do
csKeywords[kw] = '@'..kw
end
for i = 1, #csKeywords do
csKeywords[i] = nil
end
function UnK(symbol)
return csKeywords[symbol] or symbol
end
local fixChecker = {
--["System.String"] = "LuaAPI.lua_isstring",
["System.Boolean"] = "LuaTypes.LUA_TBOOLEAN == LuaAPI.lua_type",
["System.Byte"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
["System.Char"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
--["System.Decimal"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
["System.Double"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
["System.Int16"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
["System.Int32"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
--["System.Int64"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
["System.SByte"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
["System.Single"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
["System.UInt16"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
["System.UInt32"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
--["System.UInt64"] = "LuaTypes.LUA_TNUMBER == LuaAPI.lua_type",
["System.IntPtr"] = "LuaTypes.LUA_TLIGHTUSERDATA == LuaAPI.lua_type",
}
local typedCaster = {
["System.Byte"] = "LuaAPI.xlua_tointeger",
["System.Char"] = "LuaAPI.xlua_tointeger",
["System.Int16"] = "LuaAPI.xlua_tointeger",
["System.SByte"] = "LuaAPI.xlua_tointeger",
["System.Single"] = "LuaAPI.lua_tonumber",
["System.UInt16"] = "LuaAPI.xlua_tointeger",
}
local fixCaster = {
["System.Double"] = "LuaAPI.lua_tonumber",
["System.String"] = "LuaAPI.lua_tostring",
["System.Boolean"] = "LuaAPI.lua_toboolean",
["System.Byte[]"] = "LuaAPI.lua_tobytes",
["System.IntPtr"] = "LuaAPI.lua_touserdata",
["System.UInt32"] = "LuaAPI.xlua_touint",
["System.UInt64"] = "LuaAPI.lua_touint64",
["System.Int32"] = "LuaAPI.xlua_tointeger",
["System.Int64"] = "LuaAPI.lua_toint64",
}
local fixPush = {
["System.Byte"] = "LuaAPI.xlua_pushinteger",
["System.Char"] = "LuaAPI.xlua_pushinteger",
["System.Int16"] = "LuaAPI.xlua_pushinteger",
["System.Int32"] = "LuaAPI.xlua_pushinteger",
["System.Int64"] = "LuaAPI.lua_pushint64",
["System.SByte"] = "LuaAPI.xlua_pushinteger",
["System.Single"] = "LuaAPI.lua_pushnumber",
["System.UInt16"] = "LuaAPI.xlua_pushinteger",
["System.UInt32"] = "LuaAPI.xlua_pushuint",
["System.UInt64"] = "LuaAPI.lua_pushuint64",
["System.Double"] = "LuaAPI.lua_pushnumber",
["System.String"] = "LuaAPI.lua_pushstring",
["System.Byte[]"] = "LuaAPI.lua_pushstring",
["System.Boolean"] = "LuaAPI.lua_pushboolean",
["System.IntPtr"] = "LuaAPI.lua_pushlightuserdata",
["System.Decimal"] = "translator.PushDecimal",
["System.Object"] = "translator.PushAny",
}
local notranslator = {
["System.Byte"] = true,
["System.Char"] = true,
["System.Int16"] = true,
["System.Int32"] = true,
["System.Int64"] = true,
["System.SByte"] = true,
["System.Single"] = true,
["System.UInt16"] = true,
["System.UInt32"] = true,
["System.UInt64"] = true,
["System.Double"] = true,
["System.String"] = true,
["System.Boolean"] = true,
["System.Void"] = true,
["System.IntPtr"] = true,
["System.Byte[]"] = true,
}
function ForEachCsList(...)
local list_count = select('#', ...) - 1
local callback = select(list_count + 1, ...)
for i = 1, list_count do
local list = select(i, ...)
for i = 0, (list.Count or list.Length) - 1 do
callback(list[i], i)
end
end
end
function CalcCsList(list, predicate)
local count = 0
for i = 0, (list.Count or list.Length) - 1 do
if predicate(list[i], i) then count = count + 1 end
end
return count
end
function IfAny(list, predicate)
for i = 0, (list.Count or list.Length) - 1 do
if predicate(list[i], i) then return true end
end
return false
end
local genPushAndUpdateTypes
function SetGenPushAndUpdateTypes(list)
genPushAndUpdateTypes = {}
ForEachCsList(list, function(t)
genPushAndUpdateTypes[t] = true
end)
end
local xLuaClasses
function SetXLuaClasses(list)
xLuaClasses = {}
ForEachCsList(list, function(t)
xLuaClasses[t.Name] = true
end)
end
local objType = typeof(CS.System.Object)
local valueType = typeof(CS.System.ValueType)
local function _CsFullTypeName(t)
if t.IsArray then
local element_name, element_is_array = _CsFullTypeName(t:GetElementType())
if element_is_array then
local bracket_pos = element_name:find('%[')
return element_name:sub(1, bracket_pos - 1) .. '[' .. string.rep(',', t:GetArrayRank() - 1) .. ']' .. element_name:sub(bracket_pos, -1), true
else
return element_name .. '[' .. string.rep(',', t:GetArrayRank() - 1) .. ']', true
end
elseif t.IsByRef then
return _CsFullTypeName(t:GetElementType())
elseif t.IsGenericParameter then
return (t.BaseType == objType or t.BaseType == valueType) and t.Name or _CsFullTypeName(t.BaseType) --TODO:应该判断是否类型约束
end
local name = t.FullName:gsub("&", ""):gsub("%+", ".")
if not t.IsGenericType then
return friendlyNameMap[name] or name
end
local genericParameter = ""
ForEachCsList(t:GetGenericArguments(), function(at, ati)
if ati ~= 0 then genericParameter = genericParameter .. ', ' end
genericParameter = genericParameter .. _CsFullTypeName(at)
end)
return name:gsub("`%d+", '<' .. genericParameter .. '>'):gsub("%[[^,%]].*", ""), false
end
function CsFullTypeName(t)
if t.DeclaringType then
local name = _CsFullTypeName(t)
local declaringTypeName = _CsFullTypeName(t.DeclaringType);
return xLuaClasses[declaringTypeName] and ("global::" .. name) or name
else
local name = _CsFullTypeName(t)
return xLuaClasses[name] and ("global::" .. name) or name
end
end
function CSVariableName(t)
if t.IsArray then
return CSVariableName(t:GetElementType()) .. '_'.. t:GetArrayRank() ..'_'
end
return t:ToString():gsub("&", ""):gsub("%+", ""):gsub("`", "_"):gsub("%.", ""):gsub("%[", "_"):gsub("%]", "_"):gsub(",", "")
end
local function getSafeFullName(t)
if t == nil then
return ""
end
if t.IsGenericParameter then
return t.BaseType == objType and t.Name or getSafeFullName(t.BaseType)
end
if not t.FullName then return "" end
return t.FullName:gsub("&", "")
end
function GetCheckStatement(t, idx, is_v_params)
local cond_start = is_v_params and "(LuaTypes.LUA_TNONE == LuaAPI.lua_type(L, ".. idx ..") || " or ""
local cond_end = is_v_params and ")" or ""
local testname = getSafeFullName(t)
if testname == "System.String" or testname == "System.Byte[]" then
return cond_start .. "(LuaAPI.lua_isnil(L, " .. idx .. ") || LuaAPI.lua_type(L, ".. idx ..") == LuaTypes.LUA_TSTRING)" .. cond_end
elseif testname == "System.Int64" then
return cond_start .. "(LuaTypes.LUA_TNUMBER == LuaAPI.lua_type(L, ".. idx ..") || LuaAPI.lua_isint64(L, ".. idx .."))" .. cond_end
elseif testname == "System.UInt64" then
return cond_start .. "(LuaTypes.LUA_TNUMBER == LuaAPI.lua_type(L, ".. idx ..") || LuaAPI.lua_isuint64(L, ".. idx .."))" .. cond_end
elseif testname == "System.Decimal" then
return cond_start .. "(LuaTypes.LUA_TNUMBER == LuaAPI.lua_type(L, ".. idx ..") || translator.IsDecimal(L, ".. idx .."))" .. cond_end
elseif testname == "XLua.LuaTable" then
return cond_start .. "(LuaAPI.lua_isnil(L, " .. idx .. ") || LuaAPI.lua_type(L, ".. idx ..") == LuaTypes.LUA_TTABLE)" .. cond_end
elseif testname == "XLua.LuaFunction" then
return cond_start .. "(LuaAPI.lua_isnil(L, " .. idx .. ") || LuaAPI.lua_type(L, ".. idx ..") == LuaTypes.LUA_TFUNCTION)" .. cond_end
end
return cond_start .. (fixChecker[testname] or ("translator.Assignable<" .. CsFullTypeName(t).. ">")) .. "(L, ".. idx ..")" .. cond_end
end
local delegateType = typeof(CS.System.Delegate)
local ExtensionAttribute = typeof(CS.System.Runtime.CompilerServices.ExtensionAttribute)
function IsExtensionMethod(method)
return method:IsDefined(ExtensionAttribute, false)
end
function IsDelegate(t)
return delegateType:IsAssignableFrom(t)
end
function MethodParameters(method)
if not IsExtensionMethod(method) then
return method:GetParameters()
else
local parameters = method:GetParameters()
if parameters[0].ParameterType.IsInterface then
return parameters
end
local ret = {}
for i = 1, parameters.Length - 1 do
ret[i - 1] = parameters[i]
end
ret.Length = parameters.Length - 1
return ret
end
end
function IsStruct(t)
if t.IsByRef then t = t:GetElementType() end
return t.IsValueType and not t.IsPrimitive
end
function NeedUpdate(t)
if t.IsByRef then t = t:GetElementType() end
return t.IsValueType and not t.IsPrimitive and not t.IsEnum and t ~= typeof(CS.System.Decimal)
end
function GetCasterStatement(t, idx, var_name, need_declare, is_v_params)
local testname = getSafeFullName(t)
local statement = ""
local is_struct = IsStruct(t)
if need_declare then
statement = CsFullTypeName(t) .. " " .. var_name
if is_struct and not typedCaster[testname] and not fixCaster[testname] then
statement = statement .. ";"
else
statement = statement .. " = "
end
elseif not is_struct then
statement = var_name .. " = "
end
if is_v_params then
return statement .. "translator.GetParams<" .. CsFullTypeName(t:GetElementType()).. ">" .. "(L, ".. idx ..")"
elseif typedCaster[testname] then
return statement .. "(" .. CsFullTypeName(t) .. ")" ..typedCaster[testname] .. "(L, ".. idx ..")"
elseif IsDelegate(t) then
return statement .. "translator.GetDelegate<" .. CsFullTypeName(t).. ">" .. "(L, ".. idx ..")"
elseif fixCaster[testname] then
return statement .. fixCaster[testname] .. "(L, ".. idx ..")"
elseif testname == "System.Object" then
return statement .. "translator.GetObject(L, ".. idx ..", typeof(" .. CsFullTypeName(t) .."))"
elseif is_struct then
return statement .. "translator.Get(L, ".. idx ..", out " .. var_name .. ")"
elseif t.IsGenericParameter and not t.DeclaringMethod then
return statement .. "translator.GetByType<"..t.Name..">(L, ".. idx ..")"
else
return statement .. "("..CsFullTypeName(t)..")translator.GetObject(L, ".. idx ..", typeof(" .. CsFullTypeName(t) .."))"
end
end
local paramsAttriType = typeof(CS.System.ParamArrayAttribute)
function IsParams(pi)
if (not pi.IsDefined) then
return pi.IsParamArray
end
return pi:IsDefined(paramsAttriType, false)
end
local obsoluteAttriType = typeof(CS.System.ObsoleteAttribute)
function IsObsolute(f)
return f:IsDefined(obsoluteAttriType, false)
end
local objectType = typeof(CS.System.Object)
function GetSelfStatement(t)
local fulltypename = CsFullTypeName(t)
local is_struct = IsStruct(t)
if is_struct then
return fulltypename .. " gen_to_be_invoked;translator.Get(L, 1, out gen_to_be_invoked)"
else
if t == objectType then
return "object gen_to_be_invoked = translator.FastGetCSObj(L, 1)"
else
return fulltypename .. " gen_to_be_invoked = (" .. fulltypename .. ")translator.FastGetCSObj(L, 1)"
end
end
end
local GetNullableUnderlyingType = CS.System.Nullable.GetUnderlyingType
function GetPushStatement(t, variable, is_v_params)
if is_v_params then
local item_push = GetPushStatement(t:GetElementType(), variable..'[__gen_i]')
return 'if ('.. variable ..' != null) { for (int __gen_i = 0; __gen_i < ' .. variable .. '.Length; ++__gen_i) ' .. item_push .. '; }'
end
if t.IsByRef then t = t:GetElementType() end
local testname = getSafeFullName(t)
if fixPush[testname] then
return fixPush[testname] .. "(L, ".. variable ..")"
elseif genPushAndUpdateTypes[t] then
return "translator.Push".. CSVariableName(t) .."(L, "..variable..")"
elseif t.IsGenericParameter and not t.DeclaringMethod then
return "translator.PushByType(L, "..variable..")"
elseif t.IsInterface or GetNullableUnderlyingType(t) then
return "translator.PushAny(L, "..variable..")"
else
return "translator.Push(L, "..variable..")"
end
end
function GetUpdateStatement(t, idx, variable)
if t.IsByRef then t = t:GetElementType() end
if typeof(CS.System.Decimal) == t then error('Decimal not update!') end
if genPushAndUpdateTypes[t] then
return "translator.Update".. CSVariableName(t) .."(L, ".. idx ..", "..variable..")"
else
return "translator.Update(L, ".. idx ..", "..variable..")"
end
end
function JustLuaType(t)
return notranslator[getSafeFullName(t)]
end
function CallNeedTranslator(overload, isdelegate)
if not overload.IsStatic and not isdelegate then return true end
local ret_type_name = getSafeFullName(overload.ReturnType)
if not notranslator[ret_type_name] then return true end
local parameters = overload:GetParameters()
return IfAny(overload:GetParameters(), function(parameter)
return IsParams(parameter) or (not notranslator[getSafeFullName(parameter.ParameterType)])
end)
end
function MethodCallNeedTranslator(method)
return IfAny(method.Overloads, function(overload) return CallNeedTranslator(overload) end)
end
function AccessorNeedTranslator(accessor)
return not accessor.IsStatic or not JustLuaType(accessor.Type)
end
function PushObjectNeedTranslator(type_info)
return IfAny(type_info.FieldInfos, function(field_info) return not JustLuaType(field_info.Type) end)
end
local GenericParameterAttributes = CS.System.Reflection.GenericParameterAttributes
local enum_and_op = debug.getmetatable(CS.System.Reflection.BindingFlags.Public).__band
local has_generic_flag = function(f1, f2)
return (f1 ~= GenericParameterAttributes.None) and (enum_and_op(f1, f2) == f2)
end
function GenericArgumentList(type)
local generic_arg_list = ""
local type_constraints = ""
if type.IsGenericTypeDefinition then
generic_arg_list = "<"
local constraints = {}
ForEachCsList(type:GetGenericArguments(), function(generic_arg, gai)
local constraint = {}
if gai ~= 0 then generic_arg_list = generic_arg_list .. ", " end
generic_arg_list = generic_arg_list .. generic_arg.Name
if has_generic_flag(generic_arg.GenericParameterAttributes, GenericParameterAttributes.ReferenceTypeConstraint) then
table.insert(constraint, 'class')
end
if has_generic_flag(generic_arg.GenericParameterAttributes, GenericParameterAttributes.NotNullableValueTypeConstraint) then
table.insert(constraint, 'struct')
end
ForEachCsList(generic_arg:GetGenericParameterConstraints(), function(gpc)
if gpc ~= typeof(CS.System.ValueType) or not has_generic_flag(generic_arg.GenericParameterAttributes, GenericParameterAttributes.NotNullableValueTypeConstraint) then
table.insert(constraint, CsFullTypeName(gpc))
end
end)
if not has_generic_flag(generic_arg.GenericParameterAttributes, GenericParameterAttributes.NotNullableValueTypeConstraint) and has_generic_flag(generic_arg.GenericParameterAttributes, GenericParameterAttributes.DefaultConstructorConstraint) then
table.insert(constraint, 'new()')
end
if #constraint > 0 then
table.insert(constraints, 'where ' .. generic_arg.Name .. ' : ' .. table.concat(constraint, ','))
end
end)
generic_arg_list = generic_arg_list .. ">"
if #constraints > 0 then
type_constraints = table.concat(constraints, ',')
end
end
return generic_arg_list, type_constraints
end
function LocalName(name)
return "_" .. name
end