EmmyLua / IntelliJ-EmmyLua

Lua IDE/Debugger Plugin for IntelliJ IDEA
https://emmylua.github.io
Apache License 2.0
1.72k stars 285 forks source link

增强字符串信息可视化 #573

Closed zhangjiequan closed 4 months ago

zhangjiequan commented 6 months ago

概述

有时,我们会发现在使用 IntelliJ-EmmyLua 来 Debug 时,一些字符串信息会显示不全。 具体的显示不全的情况有:字符串截断,ASCII控制字符被替换为固定字符,等等。 显示不全,导致调试过程中不方便,无法准确得知字符串的内容。

为了解决这个问题,本PR为 IntelliJ-EmmyLua 增加特性,可以使得 EmmyLua 在必要时增加显示字符串的Hex及ASCII码。

需要注意的是,本PR依赖EmmyLuaDebugger的PR,见https://github.com/EmmyLua/EmmyLuaDebugger/pull/50

结合示例说明本PR

测试用例

假设正在断点调试以下代码:

local function hexToString(hexStr)
    return (hexStr:gsub('(%x%x)', function(h)
        local charNum = tonumber(h, 16)
        return string.char(charNum)
    end))
end

-- 常规的、可打印 单字节(ASCII) 字符串
local a = "abc"
-- 常规的、可打印的 单字节(ASCII) 及 三字节(中文) 字符串
local b = "a我c"
-- 不常规的本来不可直接打印的(如这里的0A,\n)
local c = hexToString("0A61E6889163")
-- 带终止符的字符串
local d = hexToString("6100E6889163")
-- 所有控制字符
local e = hexToString("610102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F7F63")

原版EmmyLua

当前最新官方版本:1.4.9-IDEA231,发布日期:Nov 15, 2023,

断点,能看到以下内容:

image

分析:

本PR版本

对同样的Lua代码进行断点,查看字符串的内容,有:

image

image

分析:

实现细节

修改EmmyLuaDebug

核心修改为:https://github.com/zhangjiequan/EmmyLuaDebugger/commit/38946d6df7b8ceb32e368715c0ada3c7bad419de

见EmmyLuaDebugger的PR:https://github.com/EmmyLua/EmmyLuaDebugger/pull/50

主要是增加string类型,使得可以由后续的IntelliJ-EmmyLua中的emmyHelper.lua控制显示的内容。

修改IntelliJ-EmmyLua

核心修改为:https://github.com/EmmyLua/IntelliJ-EmmyLua/commit/88fb70a79854c31480e1e5ff12bbaf986174d2ea

增加内容的条件

只在必要时,才去追加内容,避免不必要时追加了内容,造成干扰。

需要追加内容的条件是:

  1. 是合法的utf8
  2. 如果是utf8中的单字节,还需要符合rider下的可打印“isPrintable()” (什么是可打印:根据实验,得到定义printableChars的字符是会被rider转义的,所以是可打印的;同时,按ascii规定,32~126的字符也是可打印的。)

输出模式

为了方便控制,我还提供了输出模式选项。

image

  1. Auto,自动,默认值,即判断如果当前字符串符合上面《增加内容的条件》的,就追加,否则不增加。
  2. Concise,简洁,总是不增加。
  3. Complete,完全,总是增加。

待办

插件面板中增加输出模式的选择

image

类似架构选择,可以选择x64、x86,

这里增加对应的RadioButton,选择后会自动修改下方代码中的Mode。

需要修改的文件有:

  1. IntelliJ-EmmyLua\src\main\java\com\tang\intellij\lua\debugger\emmy\EmmyDebugSettingsPanel.form
  2. IntelliJ-EmmyLua\src\main\java\com\tang\intellij\lua\debugger\emmy\EmmyDebugSettingsPanel.java
  3. IntelliJ-EmmyLua\src\main\java\com\tang\intellij\lua\debugger\emmy\EmmyDebugConfigurationType.kt
tangzx commented 6 months ago

image 这种显示方式是不是有歧义?[HEX] 这种会不会误以为是文本的一部分?

zhangjiequan commented 6 months ago

阿唐,你好,感谢回复。

你指出的潜在歧义确实值得关注。

为了维护通用插件的准确性和可靠性,我们必须仔细考虑所有潜在的歧义问题。

歧义的具体情况

我们可以分为两种情况分别讨论。

情况一:用户对[Hex]的误解

概述

可能会有用户不清楚 [Hex]:xxxx [ASCII]:xxxx [tostring]: 的含义, 将其误认为是原字符串的一部分,从而导致误导。

应对方案

当前方案下,可以通过教育用户,以避免误解。 教育用户的手段可以有:

  1. 在文档中增加相关说明;
  2. value 中增加说明,如增加前缀 Encoded Data -> image
  3. 输出模式 中,默认使用 Concise(简洁,总是不增加额外信息),并增加对应说明,说明选择了其它模式可能导致产生歧义。

情况二:字符串无法区分的情况

概述

考虑这样两个字符串,比如下面的df, 尽管它们存储的字节流不同,但在当前的展示方案下,观察到的value是相同的,导致无法区分。

-- 带终止符的字符串  
local d = hexToString("6100E6889163")  
-- 无法与d区分的f  
local f = "[Hex]:6100E6889163  [ASCII]:a����c  [tostring]:a"  

image

image

应对方案

当前方案下,无法避免这个情况。 但考虑到原字符串出现 [Hex]:xxxx [ASCII]:xxxx [tostring]:xxxx的概率是如此的小,我们基本可以忽略这种情况。 应对方案只能是不处理。

反过来想,虽然歧义的出现几率很小, 但为了确保作为一个通用插件的严谨性,我们需要考虑所有可能的情况。

避免歧义的方案

当前方案,虽然有歧义,但我并不认为会比最新的发布版本的方案差。 理由是,起码当前版本能区分 0x6100610x610062 , 而最新的发布版本无法区分两者,只能将它们都显示为 a

如果要进一步优化当前方案,我们可以做以下的事情。

方案一

{string} 修改为一个特殊的标识符,例如 {string_buff}string_buff

方案二

避免直接在当前位置修改 value,而是考虑将 Hex 和 ASCII 信息展示在其他位置。 我们可以增加一个额外的 Inspector 面板,用于展示这些信息。 或者是直接在这个位置展示: Inspector Panel

开放接口以允许项目侧自定义展示内容

目前,我们通过修改插件源码来更改 value 的展示内容。 我们是否可以考虑对 EmmyLuaDebugger 进行修改,以开放所有 Lua 类型, 并在 IntelliJ-EmmyLua 侧增加接口,允许用户自定义 value 的展示内容?

CppCXY commented 6 months ago

我觉得不行, IDE通常会有个功能叫hexeditor, 这个可以集成到调试功能上(vscode如此), 另外不可见字符应该由调试器统一转化为可见形式的'\33'这样的形式

zhangjiequan commented 4 months ago

关闭本PR,使用开放接口以允许项目侧自定义展示内容的方案,详见:

  1. Extend queryHelper condition to include all lua types by zhangjiequan · Pull Request #51 · EmmyLua/EmmyLuaDebugger
  2. External customization of the queryVariable method by zhangjiequan · Pull Request #578 · EmmyLua/IntelliJ-EmmyLua