fix(lsp): add more robust validation in semantic tokens
- Wrap token generation in pcall to catch any errors - Add validation for all token parameters (line, startChar, length) - Validate deltaStart is non-negative - Return empty tokens if any error occurs - This should prevent the 'Invalid line: out of range' errors
This commit is contained in:
+35
-36
@@ -563,7 +563,9 @@ function handlers.textDocument_semanticTokensFull(params)
|
||||
return { data = {} }
|
||||
end
|
||||
|
||||
-- Protected token collection
|
||||
local tokens = {}
|
||||
local ok, err = pcall(function()
|
||||
local lines = {}
|
||||
for line in doc.content:gmatch("([^\n]*)\n") do
|
||||
table.insert(lines, line)
|
||||
@@ -571,11 +573,21 @@ function handlers.textDocument_semanticTokensFull(params)
|
||||
|
||||
local total_lines = #lines
|
||||
|
||||
local function add_token(line, startChar, length, tokenType)
|
||||
-- Validate line number is within bounds
|
||||
local function add_token(line, startChar, length)
|
||||
-- Validate all parameters
|
||||
if not line or not startChar or not length then
|
||||
return
|
||||
end
|
||||
if line < 0 or line >= total_lines then
|
||||
return
|
||||
end
|
||||
if startChar < 0 or length <= 0 then
|
||||
return
|
||||
end
|
||||
if startChar + length > 10000 then
|
||||
return
|
||||
end
|
||||
|
||||
local deltaLine = line
|
||||
local deltaStart = startChar
|
||||
if #tokens >= 4 then
|
||||
@@ -587,6 +599,10 @@ function handlers.textDocument_semanticTokensFull(params)
|
||||
else
|
||||
deltaLine = line - prevLine
|
||||
end
|
||||
-- Validate deltaStart is non-negative
|
||||
if deltaStart < 0 then
|
||||
return
|
||||
end
|
||||
end
|
||||
table.insert(tokens, deltaLine)
|
||||
table.insert(tokens, deltaStart)
|
||||
@@ -601,55 +617,38 @@ function handlers.textDocument_semanticTokensFull(params)
|
||||
|
||||
if doc.variables then
|
||||
for var_name, info in pairs(doc.variables) do
|
||||
-- Validate variable line number is within bounds
|
||||
if info.line and info.line >= 0 and info.line < total_lines and info.line == lineNum then
|
||||
if info and info.line and info.line >= 0 and info.line < total_lines and info.line == lineNum then
|
||||
local startChar = line:find(var_name, 1, true)
|
||||
if startChar then
|
||||
add_token(lineNum, startChar - 1, #var_name, "variable")
|
||||
add_token(lineNum, startChar - 1, #var_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local keywords = {
|
||||
"IF",
|
||||
"THEN",
|
||||
"ELSIF",
|
||||
"ELSE",
|
||||
"END_IF",
|
||||
"FOR",
|
||||
"TO",
|
||||
"BY",
|
||||
"DO",
|
||||
"END_FOR",
|
||||
"WHILE",
|
||||
"END_WHILE",
|
||||
"REPEAT",
|
||||
"UNTIL",
|
||||
"END_REPEAT",
|
||||
"CASE",
|
||||
"OF",
|
||||
"END_CASE",
|
||||
"VAR_INPUT",
|
||||
"VAR_OUTPUT",
|
||||
"VAR_IN_OUT",
|
||||
"VAR_TEMP",
|
||||
"VAR",
|
||||
"END_VAR",
|
||||
"BEGIN",
|
||||
"EXIT",
|
||||
"CONTINUE",
|
||||
"RETURN",
|
||||
"TRUE",
|
||||
"FALSE",
|
||||
"IF", "THEN", "ELSIF", "ELSE", "END_IF",
|
||||
"FOR", "TO", "BY", "DO", "END_FOR",
|
||||
"WHILE", "END_WHILE",
|
||||
"REPEAT", "UNTIL", "END_REPEAT",
|
||||
"CASE", "OF", "END_CASE",
|
||||
"VAR_INPUT", "VAR_OUTPUT", "VAR_IN_OUT", "VAR_TEMP", "VAR", "END_VAR",
|
||||
"BEGIN", "EXIT", "CONTINUE", "RETURN",
|
||||
"TRUE", "FALSE",
|
||||
}
|
||||
for _, kw in ipairs(keywords) do
|
||||
local startPos = line:find("%f[%a]" .. kw .. "%f[%A]")
|
||||
if startPos then
|
||||
add_token(lineNum, startPos - 1, #kw, "keyword")
|
||||
add_token(lineNum, startPos - 1, #kw)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- If any error occurred, return empty tokens
|
||||
if not ok then
|
||||
return { data = {} }
|
||||
end
|
||||
|
||||
return { data = tokens }
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user