feat: add builtin types/functions to diagnostics and completions
Files Modified/Created: - src/builtin_instructions.lua - NEW: Contains all TIA Portal built-in types, FBs, and functions - src/diagnostics.lua - Added missing data types + builtin instruction checking - src/main.lua - Added completion support for built-in types/F Bs/functions - src/plc_json.lua - Added .db file parsing + BOM handling fixes - lua/scl/blink_cmp_source.lua - Extended completion with all built-in types/F Bs/functions - src/node-types.json - Added node types for parser - AGENTS.md - Updated documentation Features Added: 1. Diagnostics - No more false "Unknown data type" warnings for: - All elementary types (USINT, SINT, UINT, UDINT, LINT, ULINT, TOD, DTL, etc.) - Timer/counter types (IEC_TON, TOF, TP, CTU, CTD, CTUD) - TIA Portal built-in FBs and functions 2. Auto-completion - Shows in VAR section after :: - 28 elementary data types - 23 built-in function blocks (TON, TOF, TP, CTU, CTD, CTUD, R_TRIG, F_TRIG, etc.) - 80+ built-in functions (ADD, SUB, MUL, DIV, SIN, COS, SQRT, etc.)
This commit is contained in:
@@ -34,10 +34,31 @@ function M.is_available(context)
|
||||
local prev_char = col > 1 and line:sub(col - 1, col - 1) or ""
|
||||
|
||||
-- Only trigger on our specific characters (including space for := assignments)
|
||||
if char_at == "." or char_at == "(" or char_at == "#" or char_at == '"' or char_at == " " or
|
||||
prev_char == "." or prev_char == "(" or prev_char == "#" or prev_char == '"' then
|
||||
if char_at == "." or char_at == "(" or char_at == "#" or char_at == '"' or char_at == " " or char_at == ":" or
|
||||
prev_char == "." or prev_char == "(" or prev_char == "#" or prev_char == '"' or prev_char == " " or prev_char == ":" then
|
||||
return true
|
||||
end
|
||||
|
||||
-- Also trigger when typing a word character if we're in VAR section (type declaration)
|
||||
if char_at:match("[%w_]") or prev_char:match("[%w_]") then
|
||||
-- Check if we're in VAR section
|
||||
local in_var = false
|
||||
local lines = vim.api.nvim_buf_get_lines(context.bufnr, 0, row, false)
|
||||
for i = 1, #lines do
|
||||
local l = lines[i]:gsub("^%s+", ""):gsub("%s+$", "")
|
||||
if l:match("^END_VAR") then
|
||||
in_var = false
|
||||
elseif l:match("^VAR%s*$") or l:match("^VAR$") or l:match("^VAR_INPUT") or l:match("^VAR_OUTPUT") or l:match("^VAR_IN_OUT") or l:match("^VAR_TEMP") then
|
||||
in_var = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Also check current line - if it has ":" followed by space or word, we're declaring a type
|
||||
local line_before = col > 1 and line:sub(1, col - 1) or ""
|
||||
if in_var and (line_before:match(":%s*$") or line_before:match(":%s+$")) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
@@ -779,10 +800,69 @@ function M:get_completions(context, callback)
|
||||
})
|
||||
end
|
||||
|
||||
-- Add basic types
|
||||
for _, t in ipairs({ "Bool", "Int", "DInt", "Real", "Word", "DWord", "Byte", "Time", "String", "SINT", "USINT", "UINT", "LREAL" }) do
|
||||
-- Add basic types - expanded list
|
||||
local basic_types = {
|
||||
-- Elementary types
|
||||
"BOOL", "BYTE", "WORD", "DWORD", "LWORD",
|
||||
"CHAR", "WCHAR", "STRING", "WSTRING",
|
||||
"INT", "DINT", "LINT", "USINT", "SINT", "UINT", "UDINT", "ULINT",
|
||||
"REAL", "LREAL",
|
||||
"TIME", "DATE", "TOD", "TIME_OF_DAY", "DATE_AND_TIME", "DT", "S5TIME", "LTIME", "DTL",
|
||||
-- Timer and counter types
|
||||
"IEC_TIMER", "TON_TIME", "TOF_TIME", "TONR_TIME", "TP_TIME",
|
||||
"IEC_TON", "IEC_TOF", "IEC_TP", "IEC_COUNTER",
|
||||
"CTU", "CTD", "CTUD",
|
||||
}
|
||||
for _, t in ipairs(basic_types) do
|
||||
table.insert(items, { label = t, kind = 19 })
|
||||
end
|
||||
|
||||
-- Add built-in function blocks
|
||||
local builtin_fbs = {
|
||||
-- Timers and counters
|
||||
"TON", "TOF", "TP", "TONR",
|
||||
"CTU", "CTD", "CTUD",
|
||||
"IEC_TIMER", "IEC_TON", "IEC_TOF", "IEC_TP",
|
||||
"IEC_COUNTER", "IEC_CTU", "IEC_CTD", "IEC_CTUD",
|
||||
-- Bit logic
|
||||
"R_TRIG", "F_TRIG", "SR", "RS",
|
||||
-- Other
|
||||
"SCHEDULE", "BPM", "LOG", "DATALOG",
|
||||
}
|
||||
for _, fb in ipairs(builtin_fbs) do
|
||||
table.insert(items, { label = fb, kind = 6, detail = "Function block" })
|
||||
end
|
||||
|
||||
-- Add built-in functions
|
||||
local builtin_fcs = {
|
||||
-- Math
|
||||
"ADD", "SUB", "MUL", "DIV", "MOD", "ABS", "NEG", "SQR", "SQRT",
|
||||
"EXP", "LN", "LOG", "SIN", "COS", "TAN", "ASIN", "ACOS", "ATAN",
|
||||
"MIN", "MAX", "LIMIT", "CALCULATE",
|
||||
-- Conversion
|
||||
"CONVERT", "ROUND", "TRUNC", "CEIL", "FLOOR", "SCALE_X", "NORM_X",
|
||||
"BCD_I", "I_BCD", "DI_BCD", "DI_R", "I_DI", "R_DI", "R_DB",
|
||||
-- Move/String
|
||||
"MOVE", "FILL", "SWAP", "PEEK", "POKE",
|
||||
"LEN", "CONCAT", "LEFT", "RIGHT", "MID", "INSERT", "DELETE", "REPLACE", "FIND",
|
||||
-- Bit logic
|
||||
"AND", "OR", "XOR", "NOT", "SHL", "SHR", "ROL", "ROR", "DECO", "ENCO",
|
||||
-- Time/Date
|
||||
"T_CONV", "T_ADD", "T_SUB", "T_DIFF", "T_COMBINE",
|
||||
"DT_DATE", "DT_TOD", "DATE_TO_DTL", "DTL_TO_DATE", "TOD_TO_DTL", "DTL_TO_TOD",
|
||||
"TimeToTicks", "TicksToTime",
|
||||
-- Error handling
|
||||
"GET_ERROR", "GET_ERR_ID", "RESET_ERR", "GET_DIAG", "DPRINT",
|
||||
-- Communication
|
||||
"RDREC", "WRREC", "RALRM",
|
||||
"TSEND", "TRCV", "TCON", "TDISCON", "TSEND_C", "TRCV_C",
|
||||
"TUSEND", "TURCV", "TCONNECT", "TDISCONNECT",
|
||||
"MODBUSPN", "MODBUSCP",
|
||||
}
|
||||
for _, fc in ipairs(builtin_fcs) do
|
||||
table.insert(items, { label = fc, kind = 3, detail = "Function" })
|
||||
end
|
||||
|
||||
wrapped_callback({ items = items })
|
||||
return
|
||||
end
|
||||
@@ -827,6 +907,43 @@ function M:get_completions(context, callback)
|
||||
for _, t in ipairs({ "Bool", "Int", "DInt", "Real", "Word", "DWord", "Byte", "Time", "String", "SINT", "USINT", "UINT", "LREAL" }) do
|
||||
table.insert(items, { label = t, kind = 19 })
|
||||
end
|
||||
-- Add more basic types
|
||||
local more_types = { "BOOL", "DINT", "WORD", "DWORD", "LWORD", "CHAR", "WSTRING", "UDINT", "LINT", "ULINT", "USINT", "SINT", "DATE", "TOD", "DTL", "LTIME", "S5TIME", "TIME_OF_DAY", "DATE_AND_TIME" }
|
||||
for _, t in ipairs(more_types) do
|
||||
table.insert(items, { label = t, kind = 19 })
|
||||
end
|
||||
-- Add built-in FBs
|
||||
local builtin_fbs = {
|
||||
"TON", "TOF", "TP", "TONR",
|
||||
"CTU", "CTD", "CTUD",
|
||||
"IEC_TIMER", "IEC_TON", "IEC_TOF", "IEC_TP",
|
||||
"IEC_COUNTER", "IEC_CTU", "IEC_CTD", "IEC_CTUD",
|
||||
"R_TRIG", "F_TRIG", "SR", "RS",
|
||||
"SCHEDULE", "BPM", "LOG", "DATALOG",
|
||||
}
|
||||
for _, fb in ipairs(builtin_fbs) do
|
||||
table.insert(items, { label = fb, kind = 6, detail = "Function block" })
|
||||
end
|
||||
-- Add built-in functions
|
||||
local builtin_fcs = {
|
||||
"ADD", "SUB", "MUL", "DIV", "MOD", "ABS", "NEG", "SQR", "SQRT",
|
||||
"EXP", "LN", "LOG", "SIN", "COS", "TAN", "ASIN", "ACOS", "ATAN",
|
||||
"MIN", "MAX", "LIMIT", "CALCULATE",
|
||||
"CONVERT", "ROUND", "TRUNC", "CEIL", "FLOOR", "SCALE_X", "NORM_X",
|
||||
"BCD_I", "I_BCD", "DI_BCD", "DI_R", "I_DI", "R_DI", "R_DB",
|
||||
"MOVE", "FILL", "SWAP", "PEEK", "POKE",
|
||||
"LEN", "CONCAT", "LEFT", "RIGHT", "MID", "INSERT", "DELETE", "REPLACE", "FIND",
|
||||
"AND", "OR", "XOR", "NOT", "SHL", "SHR", "ROL", "ROR", "DECO", "ENCO",
|
||||
"T_CONV", "T_ADD", "T_SUB", "T_DIFF", "T_COMBINE",
|
||||
"DT_DATE", "DT_TOD", "DATE_TO_DTL", "DTL_TO_DATE", "TOD_TO_DTL", "DTL_TO_TOD",
|
||||
"GET_ERROR", "GET_ERR_ID", "RESET_ERR", "GET_DIAG", "DPRINT",
|
||||
"RDREC", "WRREC", "RALRM",
|
||||
"TSEND", "TRCV", "TCON", "TDISCON", "TSEND_C", "TRCV_C",
|
||||
"TUSEND", "TURCV", "MODBUSPN", "MODBUSCP",
|
||||
}
|
||||
for _, fc in ipairs(builtin_fcs) do
|
||||
table.insert(items, { label = fc, kind = 3, detail = "Function" })
|
||||
end
|
||||
wrapped_callback({ items = items })
|
||||
return
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user