Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
CapsAdmin committed Dec 1, 2024
1 parent 3b4ecd5 commit 376475e
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 76 deletions.
193 changes: 132 additions & 61 deletions nattlua/other/formating.lua
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,120 @@ local SEPARATOR = " | "
local ARROW = "->"
local TAB_WIDTH = (" "):rep(4)

local function calculate_text_positions(
str--[[#: string]],
start--[[#: number]],
stop--[[#: number]],
context_line_count--[[#: number]]
)
local lines = {}
local current_line = {}
local line_start--[[#: number | nil]]
local line_stop--[[#: number | nil]]
local char_start--[[#: number | nil]]
local char_stop--[[#: number | nil]]
local source_code_char_start--[[#: number | nil]]
local source_code_char_stop--[[#: number | nil]]

for i = 1, #str do
local char = str:sub(i, i)

if i == start then
line_start = #lines + 1
source_code_char_start = #current_line + 1
char_start = #table.concat(current_line):gsub("\t", TAB_WIDTH) + 1
end

if i == stop then
line_stop = #lines + 1
source_code_char_stop = #current_line + 1
char_stop = #table.concat(current_line):gsub("\t", TAB_WIDTH) + 1
end

if char == "\n" or i == #str then
if i == #str then table.insert(current_line, char) end

table.insert(lines, (table.concat(current_line):gsub("\t", TAB_WIDTH)))
current_line = {}
else
table.insert(current_line, char)
end
end

local start_line_context = math.max(line_start - context_line_count, 1)
local stop_line_context = math.min(line_stop + context_line_count, #lines)
local start_line_context2
local stop_line_context2

do
local line_pos = 1

for i = start, 1, -1 do
local char = str:sub(i, i)

if char == "\n" then line_pos = line_pos + 1 end

if line_pos == context_line_count or i == 1 then
for i = 1, i do
local char = str:sub(i, i)

if char == "\n" then line_pos = line_pos + 1 end
end

start_line_context2 = math.max(line_pos - context_line_count - 1, 1)
assert(start_line_context2 == start_line_context)

break
end
end
end

do
local line_pos = 1

for i = stop, #str do
local char = str:sub(i, i)

if char == "\n" then line_pos = line_pos + 1 end

if line_pos == context_line_count then
line_pos = 1

for i = 1, i do
local char = str:sub(i, i)

if char == "\n" then line_pos = line_pos + 1 end
end

stop_line_context2 = line_pos + 1
assert(stop_line_context2 == stop_line_context, "???")

break
end
end
end

for i = 1, start_line_context - 1 do
lines[i] = nil
end

for i = stop_line_context + 1, #lines do
lines[i] = nil
end

return {
start_line_context = start_line_context,
stop_line_context = stop_line_context,
lines = lines,
line_start = line_start,
line_stop = line_stop,
char_start = char_start,
char_stop = char_stop,
source_code_char_start = assert(source_code_char_start),
source_code_char_stop = assert(source_code_char_stop),
}
end

function formating.BuildSourceCodePointMessage2(
code--[[#: string]],
start--[[#: number]],
Expand All @@ -191,88 +305,45 @@ function formating.BuildSourceCodePointMessage2(

if stop < start then start, stop = stop, start end

local lines = {}
local line = {}
local line_start--[[#: number | nil]]
local line_stop--[[#: number | nil]]
local char_start--[[#: number | nil]]
local char_stop--[[#: number | nil]]
local source_code_char_start--[[#: number | nil]]
local source_code_char_stop--[[#: number | nil]]

for i = 1, #code do
local char = code:sub(i, i)

if i >= start then
if not line_start then line_start = #lines + 1 end

if not char_start then
source_code_char_start = #line + 1
char_start = #table.concat(line):gsub("\t", TAB_WIDTH) + 1
end
end

if i >= stop then
if not line_stop then line_stop = #lines + 1 end

if not char_stop then
source_code_char_stop = #line + 1
char_stop = #table.concat(line):gsub("\t", TAB_WIDTH) + 1
end
end

if char == "\n" or i == #code then
if i == #code then table.insert(line, char) end

table.insert(lines, table.concat(line))
line = {}
else
table.insert(line, char)
end
end

assert(source_code_char_start)
assert(source_code_char_stop)
local start_line_context = math.max(line_start - config.surrounding_line_count, 1)
local stop_line_context = math.min(line_stop + config.surrounding_line_count, #lines)
local number_length = #tostring(stop_line_context)
local d = calculate_text_positions(code, start, stop, config.surrounding_line_count)
local number_length = #tostring(d.stop_line_context)
local annotated = {}

for line_pos = start_line_context, stop_line_context do
local line = lines[line_pos]:gsub("\t", TAB_WIDTH)
for line_pos = d.start_line_context, d.stop_line_context do
local line = d.lines[line_pos]
local header = config.show_line_numbers == false and
"" or
stringx.pad_left(tostring(line_pos), number_length, " ") .. SEPARATOR

if line_pos == line_start and line_pos == line_stop then
if line_pos == d.line_start and line_pos == d.line_stop then
-- only spans one line
local before = line:sub(1, char_start - 1)
local between = line:sub(char_start, char_stop)
local after = line:sub(char_stop + 1, #line)
local before = line:sub(1, d.char_start - 1)
local between = line:sub(d.char_start, d.char_stop)
local after = line:sub(d.char_stop + 1, #line)

if char_start > #line then between = between .. "\\n" end
if d.char_start > #line then between = between .. "\\n" end

before = header .. before
table.insert(annotated, before .. between .. after)
table.insert(annotated, (" "):rep(#before) .. ("^"):rep(#between))
elseif line_pos == line_start then
elseif line_pos == d.line_start then
-- multiple line span, first line
local before = line:sub(1, char_start - 1)
local after = line:sub(char_start, #line)
local before = line:sub(1, d.char_start - 1)
local after = line:sub(d.char_start, #line)

-- newline
if char_start > #line then after = "\\n" end
if d.char_start > #line then after = "\\n" end

before = header .. before
table.insert(annotated, before .. after)
table.insert(annotated, (" "):rep(#before) .. ("^"):rep(#after))
elseif line_pos == line_stop then
elseif line_pos == d.line_stop then
-- multiple line span, last line
local before = line:sub(1, char_stop)
local after = line:sub(char_stop + 1, #line)
local before = line:sub(1, d.char_stop)
local after = line:sub(d.char_stop + 1, #line)
table.insert(annotated, header .. before .. after)
table.insert(annotated, (" "):rep(#header) .. ("^"):rep(#before))
elseif line_pos > line_start and line_pos < line_stop then
elseif line_pos > d.line_start and line_pos < d.line_stop then
-- multiple line span, in between start and stop lines
local after = line
table.insert(annotated, header .. after)
Expand Down Expand Up @@ -317,7 +388,7 @@ function formating.BuildSourceCodePointMessage2(

if path:sub(1, 1) == "@" then path = path:sub(2) end

local msg = path .. ":" .. line_start .. ":" .. source_code_char_start
local msg = path .. ":" .. d.line_start .. ":" .. d.source_code_char_start
table.insert(annotated, header .. msg)
end

Expand Down
41 changes: 26 additions & 15 deletions test/performance/lexer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,40 @@ local lua_code = assert(
"https://gist.githubusercontent.com/CapsAdmin/0bc3fce0624a72d83ff0667226511ecd/raw/b84b097b0382da524c4db36e644ee8948dd4fb20/10mb.lua"
)
)
local lexer = Lexer(Code(lua_code, "10mb.lua"))
local profiler = require("test.helpers.profiler")
profiler.Start()
collectgarbage("stop")
local formating = require("nattlua.other.formating")

do
-- should take around 1.2 seconds
local tokens = util.Measure("lexer:GetTokens() reading contents of token and parsing strings", function()
lexer:GetTokens()
end)
for i = 1, 10 do
print("point ", i)
local start = math.random(1, #lua_code)
local stop = math.min(start + math.random(1, 200), #lua_code)
formating.BuildSourceCodePointMessage(lua_code, "test", tostring(i), start, stop, math.random(1, 5))
end

do
-- should take around 0.8 seconds
local tokens = util.Measure("lexer:ReadSimple() reading only kind, start and stop", function()
lexer:ResetState()
if false then
local lexer = Lexer(Code(lua_code, "10mb.lua"))

while true do
local type = lexer:ReadSimple()
do
-- should take around 1.2 seconds
local tokens = util.Measure("lexer:GetTokens() reading contents of token and parsing strings", function()
lexer:GetTokens()
end)
end

if type == "end_of_file" then break end
end
end)
do
-- should take around 0.8 seconds
local tokens = util.Measure("lexer:ReadSimple() reading only kind, start and stop", function()
lexer:ResetState()

while true do
local type = lexer:ReadSimple()

if type == "end_of_file" then break end
end
end)
end
end

profiler.Stop()

0 comments on commit 376475e

Please sign in to comment.