LCOV - code coverage report
Current view: top level - /lua/yoda - yaml_parser.lua (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 83 83
Test Date: 2026-04-14 10:33:13 Functions: - 0 0

            Line data    Source code
       1              : -- lua/yoda/yaml_parser.lua
       2              : -- Pure Lua YAML parser for ingress-mapping.yaml structure
       3              : -- Uses unified logging system for trace debugging
       4              : 
       5            1 : local logger = require("yoda-logging.logger")
       6              : -- Refactored for low cyclomatic complexity (all functions ≤ 7)
       7              : 
       8            1 : local M = {}
       9              : 
      10              : -- ============================================================================
      11              : -- Constants (configurable via vim.g.yoda_yaml_*)
      12              : -- ============================================================================
      13              : 
      14              : -- Allow users to extend environments without modifying source (OCP principle)
      15              : local function get_known_environments()
      16           26 :   return vim.g.yoda_yaml_environments or { fastly = true, qa = true, prod = true }
      17            1 : end
      18              : 
      19              : -- Allow users to override YAML indentation if their file format differs
      20            2 : local ENVIRONMENT_INDENT = vim.g.yoda_yaml_env_indent or 2
      21            2 : local REGION_INDENT = vim.g.yoda_yaml_region_indent or 6
      22              : 
      23              : -- ============================================================================
      24              : -- Helper Functions (Low Complexity)
      25              : -- ============================================================================
      26              : 
      27              : --- Read YAML file content
      28              : --- Complexity: 2 (1 if + 1 early return)
      29              : --- @param yaml_path string Path to YAML file
      30              : --- @return boolean, string|nil Success status, content or error
      31              : local function read_yaml_file(yaml_path)
      32            9 :   local Path = require("plenary.path")
      33           27 :   local ok, content = pcall(Path.new(yaml_path).read, Path.new(yaml_path))
      34            9 :   if not ok then
      35            1 :     vim.notify("Failed to read YAML file: " .. yaml_path, vim.log.levels.ERROR)
      36            1 :     return false, nil
      37              :   end
      38            8 :   return true, content
      39            1 : end
      40              : 
      41              : --- Check if line is empty or comment
      42              : --- Complexity: 1 (1 or condition)
      43              : --- @param trimmed string Trimmed line content
      44              : --- @return boolean
      45              : local function is_skip_line(trimmed)
      46           67 :   return trimmed == "" or trimmed:match("^#") ~= nil
      47            1 : end
      48              : 
      49              : --- Extract environment name from line
      50              : --- Complexity: 3 (1 match + 1 and + 1 table lookup)
      51              : --- @param trimmed string Trimmed line content
      52              : --- @param indent number Line indentation
      53              : --- @return string|nil Environment name if valid
      54              : local function extract_environment_name(trimmed, indent)
      55           54 :   if indent ~= ENVIRONMENT_INDENT then
      56           41 :     return nil
      57              :   end
      58              : 
      59           13 :   local env_name = trimmed:match("^-%s*name:%s*(.+)")
      60           13 :   local known_envs = get_known_environments()
      61           13 :   if env_name and known_envs[env_name] then
      62           13 :     return env_name
      63              :   end
      64              :   return nil
      65            1 : end
      66              : 
      67              : --- Extract region name from line
      68              : --- Complexity: 3 (2 and conditions + 1 match)
      69              : --- @param trimmed string Trimmed line content
      70              : --- @param indent number Line indentation
      71              : --- @param current_env string|nil Current environment context
      72              : --- @return string|nil Region name if valid
      73              : local function extract_region_name(trimmed, indent, current_env)
      74           41 :   if indent ~= REGION_INDENT or not current_env then
      75           20 :     return nil
      76              :   end
      77              : 
      78           21 :   return trimmed:match("^-%s*name:%s*(.+)")
      79            1 : end
      80              : 
      81              : --- Create debug log entry for line
      82              : --- Complexity: 1 (simple format)
      83              : --- @param i number Line number
      84              : --- @param indent number Indentation
      85              : --- @param trimmed string Content
      86              : --- @return string Debug log entry
      87              : local function create_line_log(i, indent, trimmed)
      88              :   return string.format("Line %d: indent=%d content='%s'", i, indent, trimmed)
      89            1 : end
      90              : 
      91              : --- Save current environment to results
      92              : --- Complexity: 2 (1 if + simple operations)
      93              : --- @param environments table Environments map
      94              : --- @param current_env string|nil Current environment
      95              : --- @param current_regions table Current regions array
      96              : local function save_environment(environments, current_env, current_regions)
      97           21 :   if not current_env then
      98            8 :     return
      99              :   end
     100              : 
     101           13 :   environments[current_env] = current_regions
     102           13 :   logger.trace("Saved environment", { env = current_env, regions = #current_regions })
     103           14 : end
     104              : 
     105              : --- Process environment line
     106              : --- Complexity: 1 (simple operations)
     107              : --- @param env_order table Environment order array
     108              : --- @param env_name string Environment name
     109              : --- @param line_num number Line number
     110              : local function log_new_environment(env_order, env_name, line_num)
     111           13 :   table.insert(env_order, env_name)
     112           13 :   logger.trace("Found environment", { env = env_name, line = line_num })
     113           14 : end
     114              : 
     115              : --- Process region line
     116              : --- Complexity: 1 (simple operations)
     117              : --- @param current_regions table Regions array
     118              : --- @param region_name string Region name
     119              : --- @param current_env string Current environment
     120              : local function add_region(current_regions, region_name, current_env)
     121           21 :   table.insert(current_regions, region_name)
     122           21 :   logger.trace("Found region", { region = region_name, env = current_env })
     123           22 : end
     124              : 
     125              : --- Removed: write_debug_log - now handled by unified logger with file strategy
     126              : 
     127              : --- Process single YAML line
     128              : --- Complexity: 6 (1 skip + 2 env checks + 2 region checks + 1 log)
     129              : --- @param line string Line content
     130              : --- @param line_num number Line number
     131              : --- @param state table Parser state {current_env, current_regions, environments, env_order}
     132              : local function process_line(line, line_num, state)
     133           67 :   local trimmed = line:match("^%s*(.-)%s*$")
     134              : 
     135              :   -- Skip empty/comment lines
     136          134 :   if is_skip_line(trimmed) then
     137           13 :     return
     138              :   end
     139              : 
     140           54 :   local indent = #(line:match("^(%s*)") or "")
     141          108 :   logger.trace(function()
     142              :     return create_line_log(line_num, indent, trimmed)
     143           54 :   end)
     144              : 
     145              :   -- Check for environment definition
     146           54 :   local env_name = extract_environment_name(trimmed, indent)
     147           54 :   if env_name then
     148           13 :     save_environment(state.environments, state.current_env, state.current_regions)
     149           13 :     state.current_env = env_name
     150           13 :     state.current_regions = {}
     151           13 :     log_new_environment(state.env_order, env_name, line_num)
     152           13 :     return
     153              :   end
     154              : 
     155              :   -- Check for region definition
     156           41 :   local region_name = extract_region_name(trimmed, indent, state.current_env)
     157           41 :   if region_name then
     158           21 :     add_region(state.current_regions, region_name, state.current_env)
     159              :   end
     160           42 : end
     161              : 
     162              : --- Add final debug information
     163              : --- Complexity: 2 (1 loop + simple operations)
     164              : --- @param env_order table Environment order
     165              : --- @param environments table Environments map
     166              : local function finalize_debug_log(env_order, environments)
     167            8 :   logger.trace("YAML parsing complete", { env_order = env_order })
     168              : 
     169           21 :   for env_name, regions in pairs(environments) do
     170           13 :     logger.trace("Environment result", { env = env_name, regions = regions })
     171              :   end
     172            9 : end
     173              : 
     174              : --- Parse YAML file and extract environments and regions
     175              : --- Complexity: 4 (1 read check + 1 loop + 1 save + 1 finalize)
     176              : --- @param yaml_path string Path to the YAML file
     177              : --- @return table|nil Table with environment names as keys and region arrays as values
     178            1 : function M.parse_ingress_mapping(yaml_path)
     179              :   -- Input validation
     180            9 :   assert(type(yaml_path) == "string" and yaml_path ~= "", "yaml_path must be a non-empty string")
     181              : 
     182              :   -- Read file
     183            9 :   local ok, content = read_yaml_file(yaml_path)
     184            9 :   if not ok then
     185            1 :     return nil
     186              :   end
     187              : 
     188              :   -- Initialize parser state
     189            8 :   local state = {
     190              :     current_env = nil,
     191            8 :     current_regions = {},
     192            8 :     environments = {},
     193            8 :     env_order = {},
     194              :   }
     195              : 
     196              :   -- Setup debug logging with unified logger
     197            8 :   local lines = vim.split(content, "\n")
     198            8 :   logger.debug("Starting YAML parse", { file = yaml_path, lines = #lines })
     199              : 
     200              :   -- Process each line
     201           75 :   for i, line in ipairs(lines) do
     202           67 :     process_line(line, i, state)
     203              :   end
     204              : 
     205              :   -- Save final environment
     206            8 :   save_environment(state.environments, state.current_env, state.current_regions)
     207              : 
     208              :   -- Finalize debug logging
     209            8 :   finalize_debug_log(state.env_order, state.environments)
     210              : 
     211           16 :   logger.info("YAML parsing complete", {
     212            8 :     file = yaml_path,
     213            8 :     environments = #state.env_order,
     214              :   })
     215              : 
     216            8 :   return {
     217            8 :     environments = state.environments,
     218            8 :     env_order = state.env_order,
     219            8 :   }
     220            1 : end
     221              : 
     222            1 : return M
        

Generated by: LCOV version 2.0-1