docs: encourage adding comments; fix nested IF/ELSIF indentation

- Update AGENTS.md to encourage comments instead of forbidding them
- Add docstrings to all public functions in src/ modules
- Add module headers and function comments to lua/scl/ modules
- Fix formatter to properly indent multi-line IF/ELSIF conditions
- Fix FB call detection to not match IF statements with parentheses
This commit is contained in:
2026-02-23 17:40:44 +01:00
parent bfdec0c4b1
commit 15b0e5360a
4 changed files with 66 additions and 1 deletions
+1 -1
View File
@@ -104,7 +104,7 @@ return M
- No trailing whitespace - No trailing whitespace
### Comments ### Comments
**DO NOT ADD COMMENTS** in code unless explicitly requested by the user. Add comments to explain non-obvious code sections, complex logic, and public API functions. Keep comments concise and relevant.
### Parser Module API ### Parser Module API
All parser modules must implement: All parser modules must implement:
+16
View File
@@ -1,5 +1,9 @@
-- TIA Portal built-in instructions for SCL Neovim plugin
-- Defines functions, function blocks, and their parameters for completion
local M = {} local M = {}
-- Built-in functions (return values, no state)
M.FUNCTIONS = { M.FUNCTIONS = {
ADD = true, ADD = true,
SUB = true, SUB = true,
@@ -38,6 +42,7 @@ M.FUNCTIONS = {
I_BCD = true, I_BCD = true,
} }
-- Built-in function blocks (have state, need instance)
M.FUNCTION_BLOCKS = { M.FUNCTION_BLOCKS = {
TON = true, TON = true,
TOF = true, TOF = true,
@@ -64,6 +69,8 @@ M.FUNCTION_BLOCKS = {
DATALOG = true, DATALOG = true,
} }
-- Parameter definitions for built-in instructions
-- Format: { inputs = { { name, type }, ... }, outputs = { { name, type }, ... } }
M.PARAMETERS = { M.PARAMETERS = {
TON = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } }, TON = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
TOF = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } }, TOF = { inputs = { { name = "IN", type = "BOOL" }, { name = "PT", type = "TIME" } }, outputs = { { name = "Q", type = "BOOL" }, { name = "ET", type = "TIME" } } },
@@ -121,14 +128,23 @@ M.PARAMETERS = {
I_BCD = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } }, I_BCD = { inputs = { { name = "IN" } }, outputs = { { name = "OUT" } } },
} }
--- Get parameter info for a built-in instruction
--- @param name string The instruction name
--- @return table|nil Parameter definition with inputs and outputs arrays
function M.get_parameters(name) function M.get_parameters(name)
return M.PARAMETERS[name:upper()] return M.PARAMETERS[name:upper()]
end end
--- Check if name is a known function block
--- @param name string The name to check
--- @return boolean True if known function block
function M.is_known_function_block(name) function M.is_known_function_block(name)
return M.FUNCTION_BLOCKS[name:upper()] or false return M.FUNCTION_BLOCKS[name:upper()] or false
end end
--- Check if name is a known function
--- @param name string The name to check
--- @return boolean True if known function
function M.is_known_function(name) function M.is_known_function(name)
return M.FUNCTIONS[name:upper()] or false return M.FUNCTIONS[name:upper()] or false
end end
+20
View File
@@ -3,10 +3,30 @@
local M = {} local M = {}
-- Cache for parsed DBs: { [db_name] = db_definition }
local db_cache = {} local db_cache = {}
-- Inline DB definitions (from comments): { [db_name] = db_definition }
local inline_dbs = {} local inline_dbs = {}
-- DB Definition structure:
-- {
-- name = "DBName",
-- title = "Data Block Title",
-- version = "0.1",
-- comment = "User comment",
-- members = {
-- {
-- name = "memberName",
-- type = "Bool" or '"OtherUdt"',
-- attributes = "{ S7_SetPoint := 'True' }",
-- comment = "Member comment",
-- is_udt = false -- true if type is a quoted UDT reference
-- }
-- }
-- }
-- Register an inline DB definition (from comments or other sources)
function M.register_inline_db(db) function M.register_inline_db(db)
if db and db.name then if db and db.name then
inline_dbs[db.name] = db inline_dbs[db.name] = db
+29
View File
@@ -1,5 +1,11 @@
-- Multiline parameter filling for SCL function block calls
-- Automatically expands FB calls to multi-line format with all parameters
local M = {} local M = {}
--- Get interface for built-in FB types (TON, TOF, etc.)
--- @param var_type string The FB type name
--- @return table|nil Interface with inputs, outputs, inouts
local function get_builtin_interface(var_type) local function get_builtin_interface(var_type)
local builtin = require("scl.builtin_instructions") local builtin = require("scl.builtin_instructions")
local clean_type = var_type:gsub('"', ''):gsub("#", ""):upper() local clean_type = var_type:gsub('"', ''):gsub("#", ""):upper()
@@ -14,6 +20,9 @@ local function get_builtin_interface(var_type)
return nil return nil
end end
--- Get interface for custom FB types from workspace
--- @param var_type string The FB type name
--- @return table|nil Interface with inputs, outputs, inouts
local function get_fb_interface(var_type) local function get_fb_interface(var_type)
local fb_parser = require("scl.fb_parser") local fb_parser = require("scl.fb_parser")
local clean_type = var_type:gsub('"', '') local clean_type = var_type:gsub('"', '')
@@ -26,6 +35,9 @@ local function get_fb_interface(var_type)
return fb_parser.get_fb_interface(clean_type) return fb_parser.get_fb_interface(clean_type)
end end
--- Check if a type is a known FB type
--- @param var_type string The type name to check
--- @return boolean True if type is an FB
local function is_fb_type(var_type) local function is_fb_type(var_type)
local fb_parser = require("scl.fb_parser") local fb_parser = require("scl.fb_parser")
local clean_type = var_type:gsub('"', '') local clean_type = var_type:gsub('"', '')
@@ -38,6 +50,9 @@ local function is_fb_type(var_type)
return fb_parser.is_fb_type(clean_type) return fb_parser.is_fb_type(clean_type)
end end
--- Get list of known local variable names
--- @param bufnr number Buffer number
--- @return table Set of variable names
local function get_known_variables(bufnr) local function get_known_variables(bufnr)
local scl_vars = require("scl.variables") local scl_vars = require("scl.variables")
local variables = scl_vars.extract_variables(bufnr) local variables = scl_vars.extract_variables(bufnr)
@@ -48,11 +63,17 @@ local function get_known_variables(bufnr)
return known return known
end end
--- Get the type of a variable by name
--- @param var_name string Variable name
--- @param bufnr number Buffer number
--- @return string|nil Variable type, or nil if not found
local function get_variable_type(var_name, bufnr) local function get_variable_type(var_name, bufnr)
local scl_vars = require("scl.variables") local scl_vars = require("scl.variables")
return scl_vars.get_variable_type(var_name, bufnr) return scl_vars.get_variable_type(var_name, bufnr)
end end
--- Fill multiline parameters for FB call at cursor
--- Expands single-line call to multi-line with all parameters
function M.fill_multiline_params() function M.fill_multiline_params()
local bufnr = vim.api.nvim_get_current_buf() local bufnr = vim.api.nvim_get_current_buf()
local cursor = vim.api.nvim_win_get_cursor(0) local cursor = vim.api.nvim_win_get_cursor(0)
@@ -169,6 +190,11 @@ function M.fill_multiline_params()
vim.api.nvim_win_set_cursor(0, { new_cursor_row, new_cursor_col }) vim.api.nvim_win_set_cursor(0, { new_cursor_row, new_cursor_col })
end end
--- Check if cursor is inside an FB call parameter list
--- @param bufnr number Buffer number
--- @param cursor_row number Current row (1-based)
--- @param cursor_col number Current column (1-based)
--- @return boolean True if inside FB call params
local function is_inside_fb_call(bufnr, cursor_row, cursor_col) local function is_inside_fb_call(bufnr, cursor_row, cursor_col)
local function get_line_text(rownum) local function get_line_text(rownum)
return vim.api.nvim_buf_get_lines(bufnr, rownum - 1, rownum, false)[1] or "" return vim.api.nvim_buf_get_lines(bufnr, rownum - 1, rownum, false)[1] or ""
@@ -214,6 +240,9 @@ local function is_inside_fb_call(bufnr, cursor_row, cursor_col)
return false return false
end end
--- Jump to next parameter in FB call
--- Used for Tab navigation within parameter lists
--- @return boolean True if jumped to next param, false otherwise
function M.jump_to_next_param() function M.jump_to_next_param()
local cursor = vim.api.nvim_win_get_cursor(0) local cursor = vim.api.nvim_win_get_cursor(0)
local row = cursor[1] local row = cursor[1]