Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Conversation

zhangjiequan
Copy link

@zhangjiequan zhangjiequan commented Dec 26, 2023

概述

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

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

需要注意的是,本PR依赖EmmyLuaDebugger的PR,见EmmyLua/EmmyLuaDebugger#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

分析:

  • 观察c,我们知道,rider对0x0A(LF,换行符)进行了转义,能显示成\n。
  • 观察d,lua底层是c,c遇到0x00(终止符),就把后面的字节流忽略了。
  • 观察e,这里能看到rider对哪些ASCII控制码有做转义,没有做转义的,特别地,7F(删除符)显示成了空格。

本PR版本

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

image

image

分析:

  • 观察a、b、c,与原版没有差异,因为原版已经把足够的信息表达出来了,所以我这里追加更多信息,避免干扰(平时开发过程中,遇到的大多数情况都属于这种常规情况)。
  • 观察d、e,使用[Hex]、[ASCII]、[tostring]分割了三段字符串的表达形式:在[tostring]段,保留了原版的形式,;同时增加对应的Hex表示,以及ASCII表示。

实现细节

修改EmmyLuaDebug

核心修改为:zhangjiequan/EmmyLuaDebugger@38946d6

见EmmyLuaDebugger的PR:EmmyLua/EmmyLuaDebugger#50

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

修改IntelliJ-EmmyLua

核心修改为:88fb70a

增加内容的条件

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

需要追加内容的条件是:

  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

…cessing

Updated the debugger's string handling to provide detailed visualization, including hex representation and ASCII conversion for non-printable characters.  And formated the string output based on the defined `StringOutputMode`.
Set the default string output mode for the debugger to 'Auto' within the updateCodeImpl method. This ensures consistent string visualization behavior following the recent enhancements for hex and ASCII processing.
@tangzx
Copy link
Member

tangzx commented Dec 28, 2023

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

@zhangjiequan
Copy link
Author

zhangjiequan commented Dec 28, 2023

阿唐,你好,感谢回复。

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

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

歧义的具体情况

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

情况一:用户对[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
Copy link
Member

CppCXY commented Dec 29, 2023

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants