zoukankan      html  css  js  c++  java
  • 使用IDEA进行Lua代码调试、自动提示、代码跳转、智能重命名

    试了几个Lua IDE后,Lua Studio、Lua Glider、VS+babelua插件、Sublime都不是特别满意。直到发现了国人自创的另一个神奇工具:基于IDEA的EmmyLua插件。该插件功能非常完整:断点调试、自动提示、代码跳转、智能重命名等,可以极大地提高Lua编程的速度。界面也比较舒服。

    安装步骤

    1. 下载、安装并破解IntelliJ IDEA(我的版本是目前最新的2017.3.4)
    2. 安装EmmyLua插件 
      建议直接在IDEA工具内搜索插件安装(当然也可以下载插件到硬盘安装)。 
      (1)在启动界面点击Configure-Plugins: 
      这里写图片描述 
      (2)搜索EmmyLua,然后点Search in repositories: 
      这里写图片描述
      (3)点击右边的Install绿色按钮。安装完需要重启IDEA。
    3. 配置SDK,默认是Path路径需要有一个Lua解释器(lua.exe)。你可以在创建项目时指定其他目录。
    4. 配置其他事项。 
      (1)将*.txt识别成lua文件: 
      这里写图片描述
      (2)忽略代码提示大小写差别: 
      这里写图片描述

    创建项目

    1. 创建普通Lua项目(不依赖其他程序,如游戏引擎): 
      New-Project,然后next,填项目名、路径,点击finish。 
      在项目视图的src文件夹New一个Lua文件,可以自己print()一下,Run一下,看看有没有输出,有的话,说明SDK配置正确。 
      这里写图片描述 
      这里写图片描述

    2. 创建Unity引擎Lua项目 
      New-Modules from existing sources(注意不要选错,这里创建的是Modules,不是Project,否则等下导入不了api自动提示的library)。【这里有一个IDE Bug:第一次创建Modules,会在文件夹里生成一个.iml文件。但是如果文件夹里本来就有.iml文件,以后再点Modules from existing sources就会无法生成Modules,也就无法导入library。这个Bug我折腾了一晚上才发现的!必须删掉.iml文件,才可以重新创建Modules】 
      然后选择Unity文件夹的Lua访问根目录,我选的是Resources文件夹,因为可以从Resources作为根目录搜索lua文件。 
      然后我们测试一下断点调试功能。打开其中一个Lua文件,设置断点: 
      这里写图片描述
      然后Run-Attach To Local Process: 
      这里写图片描述 
      选择Unity进程,触发断点,说明能断点调试: 
      这里写图片描述

    Unity API代码提示

    现在Unity API代码提示是没有的,因为我们还没导入API描述的library。这个library根据你选择的Lua中间件不同而不同,所以建议是自己导出。我的Lua中间件是SLua。这里以SLua为例。 
    1.打开SLua官方自带的Unity项目,在Slua-Editor下面,新建一个SLuaApiExporter.cs脚本: 
    这里写图片描述 
    2.输入如下代码:

    using System;
    using System.Reflection;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using UnityEditor;
    using SLua;
    using System.IO;
    using UnityEngine;
    
    namespace Slua
    {
        public static class EmmyLuaApiExporter
        {
            [MenuItem("SLua/导出EmmyLuaApi", false, 14)]
            static void Gen()
            {
                string path = "./EmmyApi/";
                if (Directory.Exists(path))
                {
                    Directory.Delete(path, true);
                }
                Directory.CreateDirectory(path);
                //UnityEngine
                GenAssembly("UnityEngine", path);
                //GenAssembly("UnityEngine.UI", path);
                GenCustom(path);
            }
    
            public static void GenAssembly(string name, string path)
            {
                List<string> excludeList;
                List<string> includeList;
                CustomExport.OnGetNoUseList(out excludeList);
                CustomExport.OnGetUseList(out includeList);
                Type[] types = Assembly.Load(name).GetTypes();
                foreach (Type t in types)
                {
                    if (LuaCodeGen.filterType(t, excludeList, includeList))
                    {
                        GenType(t, false, path);
                    }
                }
            }
    
            public static void GenCustom(string path)
            {
                Type[] types = Assembly.Load("Assembly-CSharp-firstpass").GetTypes();
                foreach (Type t in types)
                {
                    if (t.IsDefined(typeof(CustomLuaClassAttribute), false))
                    {
                        GenType(t, true, path);
                    }
                }
    
                types = Assembly.Load("Assembly-CSharp").GetTypes();
                foreach (Type t in types)
                {
                    if (t.IsDefined(typeof(CustomLuaClassAttribute), false))
                    {
                        GenType(t, true, path);
                    }
                }
            }
            public static void GenType(Type t, bool custom, string path)
            {
                if (!CheckType(t, custom))
                    return;
                //TODO System.MulticastDelegate
                var sb = new StringBuilder();
                if (!CheckType(t.BaseType, custom))
                    sb.AppendFormat("---@class {0}
    ", t.Name);
                else
                    sb.AppendFormat("---@class {0} : {1}
    ", t.Name, t.BaseType.Name);
                GenTypeField(t, sb);
                sb.AppendFormat("local {0}={{ }}
    ", t.Name);
    
                GenTypeMehod(t, sb);
    
                sb.AppendFormat("{0}.{1} = {2}", t.Namespace, t.Name, t.Name);
    
                File.WriteAllText(path + t.FullName + ".lua", sb.ToString(), Encoding.UTF8);
            }
    
            static bool CheckType(Type t, bool custom)
            {
                if (t == null)
                    return false;
                if (t == typeof(System.Object))
                    return false;
                if (t.IsGenericTypeDefinition)
                    return false;
                if (t.IsDefined(typeof(ObsoleteAttribute), false))
                    return false;
                if (t == typeof(YieldInstruction))
                    return false;
                if (t == typeof(Coroutine))
                    return false;
                if (t.IsNested)
                    return false;
                if (custom && !t.IsDefined(typeof(CustomLuaClassAttribute), false))
                    return false;
                return true;
            }
    
            public static void GenTypeField(Type t, StringBuilder sb)
            {
                FieldInfo[] fields = t.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                foreach(var field in fields)
                {
                    if (field.IsDefined(typeof(DoNotToLuaAttribute), false))
                        continue;
                    sb.AppendFormat("---@field public {0} {1}
    ", field.Name, GetLuaType(field.FieldType));
                }
                PropertyInfo[] properties = t.GetProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                foreach (var pro in properties)
                {
                    if (pro.IsDefined(typeof(DoNotToLuaAttribute), false))
                        continue;
                    sb.AppendFormat("---@field public {0} {1}
    ", pro.Name, GetLuaType(pro.PropertyType));
                }
            }
    
            public static void GenTypeMehod(Type t, StringBuilder sb)
            {
                MethodInfo[] methods = t.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                foreach (var method in methods)
                {
                    if (method.IsGenericMethod)
                        continue;
                    if (method.IsDefined(typeof(DoNotToLuaAttribute), false))
                        continue;
                    if(method.Name.StartsWith("get_") || method.Name.StartsWith("set_"))
                        continue;
                    sb.AppendLine("---@public");
                    var paramstr = new StringBuilder();
                    foreach (var param in method.GetParameters())
                    {
                        sb.AppendFormat("---@param {0} {1}
    ", param.Name, GetLuaType(param.ParameterType));
                        if (paramstr.Length != 0)
                        {
                            paramstr.Append(", ");
                        }
                        paramstr.Append(param.Name);
                    }
                    sb.AppendFormat("---@return {0}
    ", method.ReturnType == null ? "void" : GetLuaType(method.ReturnType));
                    if( method.IsStatic)
                    {
                        sb.AppendFormat("function {0}.{1}({2}) end
    ", t.Name, method.Name, paramstr);
                    }
                    else
                    {
                        sb.AppendFormat("function {0}:{1}({2}) end
    ", t.Name, method.Name, paramstr);
                    }
                }
            }
    
            static string GetLuaType(Type t)
            {
                if (t.IsEnum
                    //|| t == typeof(ulong)
                    //|| t == typeof(long)
                    //|| t == typeof(int)
                    //|| t == typeof(uint)
                    //|| t == typeof(float)
                    || t == typeof(double)
                    //|| t == typeof(byte)
                    //|| t == typeof(ushort)
                    //|| t == typeof(short)
                    )
                    return "number";
                if (t == typeof(bool))
                    return "bool";
                if (t == typeof(string))
                    return "string";
                if (t == typeof(void))
                    return "void";
    
                return t.Name;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184

    3.在Unity编辑器中点击SLua-导出EmmyLuaApi 
    这里写图片描述

    4.看到Unity工程项目会多出一个EmmyApi文件夹: 
    这里写图片描述

    5.将其打包成zip文件(注意不能是rar、7z其它压缩格式!) 
    这里写图片描述

    6.在IDEA中点击File-Project Structure,Modules-选择我们的Modules-Dependencies,+号-Library-Lua Zip Library,选择我们刚才打包的zip文件。然后一直OK保存就行了。 
    这里写图片描述

    这里写图片描述

    7.测试Unity API提示功能: 
    这里写图片描述

    成功!

    其它功能

    代码跳转: 
    这里写图片描述

    智能重命名: 
    这里写图片描述 
    这里写图片描述

    后续

    本教程就到这里结束了,但是该插件还有许多有用的功能,可以自行探索,也可以加入EmmyLua的官方QQ群:29850775。群里面有许多教程,本文所用的API导出代码也是从群文件里拿出来改的。

    github: https://github.com/tangzx/IntelliJ-EmmyLua 
    oschina: http://git.oschina.net/tangzx/IntelliJ-Lua 
    IDEA Plugins : https://plugins.jetbrains.com/plugin/9768-emmylua

    最后感谢EmmyLua的作者们无私开源编写了这个强大的插件。

    参考链接:https://blog.csdn.net/sinat_24229853/article/details/79226608

                      https://blog.csdn.net/u010019717/article/details/77510066?ref=myread

  • 相关阅读:
    语法树,短语,直接短语,句柄
    理解文法和语法
    了解编译原理
    实习日记7.20
    实习日记7.19
    实习日记7.18
    实习日记7.15
    实习日记7.13-7.14
    实习日记7.12
    实习日记7.11
  • 原文地址:https://www.cnblogs.com/xiohao/p/9391411.html
Copyright © 2011-2022 走看看