Skip to content

Commit ae6bc4b

Browse files
committed
fix: invalid UTF-8 JSON in hover markdown
1 parent 7a73c78 commit ae6bc4b

5 files changed

Lines changed: 63 additions & 10 deletions

File tree

script/core/completion/completion.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1277,7 +1277,7 @@ local function insertDocEnumKey(doc, enums)
12771277
goto CONTINUE
12781278
end
12791279
enums[#enums+1] = {
1280-
label = ('%q'):format(key),
1280+
label = util.viewLiteral(key),
12811281
kind = define.CompletionItemKind.EnumMember,
12821282
id = stack(field, function (newField) ---@async
12831283
return {

script/core/hover/description.lua

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,11 @@ local function asStringView(source, literal)
6464
if config.get(guide.getUri(source), 'Lua.hover.viewString')
6565
and (source[2] == '"' or source[2] == "'")
6666
and rawLen > #literal then
67-
local view = literal
67+
local view = util.escapeInvalidUtf8(literal)
6868
local max = config.get(guide.getUri(source), 'Lua.hover.viewStringMax')
6969
if #view > max then
70-
view = view:sub(1, max) .. '...'
70+
local nextCharacter = utf8.offset(view, 0, max + 1)
71+
view = view:sub(1, nextCharacter - 1) .. '...'
7172
end
7273
local md = markdown()
7374
md:add('txt', view)
@@ -486,7 +487,7 @@ local function tryDocEnum(source)
486487
if not key then
487488
goto CONTINUE
488489
end
489-
keys[#keys+1] = ('%q'):format(key)
490+
keys[#keys+1] = util.viewLiteral(key)
490491
::CONTINUE::
491492
end
492493
end
@@ -507,7 +508,8 @@ local function tryDocEnum(source)
507508
end
508509
if field.value.type == 'integer'
509510
or field.value.type == 'string' then
510-
md:add('lua', (' %s: %s = %q,'):format(key, field.value.type, field.value[1]))
511+
local value = util.viewLiteral(field.value[1])
512+
md:add('lua', (' %s: %s = %s,'):format(key, field.value.type, value))
511513
end
512514
if field.value.type == 'binary'
513515
or field.value.type == 'unary' then

script/utility.lua

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,10 @@ local esc = {
469469
['\n'] = '\\\n',
470470
}
471471

472-
local function escapeInvalidUtf8(str)
472+
function m.escapeInvalidUtf8(str)
473+
if utf8Len(str) then
474+
return str
475+
end
473476
local result = {}
474477
local start = 1
475478
while true do
@@ -486,9 +489,7 @@ local function escapeInvalidUtf8(str)
486489
end
487490

488491
function m.viewString(str, quo)
489-
if not utf8Len(str) then
490-
str = escapeInvalidUtf8(str)
491-
end
492+
str = m.escapeInvalidUtf8(str)
492493
if not quo then
493494
if str:find('[\r\n]') then
494495
quo = '[['

test/completion/common.lua

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3879,6 +3879,24 @@ f(<??>)
38793879
},
38803880
}
38813881

3882+
TEST [[
3883+
---@enum(key) Enum
3884+
local t = {
3885+
["\xC2"] = 1,
3886+
}
3887+
3888+
---@param p Enum
3889+
local function f(p) end
3890+
3891+
f(<??>)
3892+
]]
3893+
{
3894+
{
3895+
label = '"\\194"',
3896+
kind = define.CompletionItemKind.EnumMember,
3897+
},
3898+
}
3899+
38823900
TEST [[
38833901
---@class optional
38843902
---@field enum enum

test/hover/init.lua

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ local core = require 'core.hover'
22
local files = require 'files'
33
local catch = require 'catch'
44
local config = require 'config'
5+
local json = require 'json'
56

67
rawset(_G, 'TEST', true)
78

@@ -12,8 +13,18 @@ function TEST(script)
1213
files.setText(TESTURI, newScript)
1314
local hover = core.byUri(TESTURI, catched['?'][1][1], 1)
1415
assert(hover)
16+
local value = hover:string():gsub('\r\n', '\n')
17+
assert(utf8.len(value))
18+
assert(utf8.len(json.encode {
19+
result = {
20+
contents = {
21+
kind = 'markdown',
22+
value = value,
23+
},
24+
},
25+
}))
1526
expect = expect:gsub('^[\r\n]*(.-)[\r\n]*$', '%1'):gsub('\r\n', '\n')
16-
local label = hover:string():gsub('\r\n', '\n'):match('```lua[\r\n]*(.-)[\r\n]*```')
27+
local label = value:match('```lua[\r\n]*(.-)[\r\n]*```')
1728
assert(expect == label)
1829
files.remove(TESTURI)
1930
end
@@ -373,6 +384,11 @@ local s = <?'abc中文'?>
373384
]]
374385
[[9 个字节,5 个字符]]
375386

387+
TEST [[
388+
local fail = <?"\xC2"?>
389+
]]
390+
[[1 个字节]]
391+
376392
TEST [[
377393
local n = <?0xff?>
378394
]]
@@ -2127,6 +2143,22 @@ local m = {
21272143
(enum) A
21282144
]]
21292145

2146+
TEST [[
2147+
---@enum <?Broken?>
2148+
local Broken = {
2149+
A = "\xC2",
2150+
}
2151+
]]
2152+
[[(enum) Broken]]
2153+
2154+
TEST [[
2155+
---@enum(key) <?Key?>
2156+
local Key = {
2157+
["\xC2"] = 1,
2158+
}
2159+
]]
2160+
[[(enum) Key]]
2161+
21302162
TEST [[
21312163
local <?x?> = 1 << 2
21322164
]]

0 commit comments

Comments
 (0)