Jianw
2025-05-13 3b39fe3810c3ee2ec9ec97236c1769c5c85e062c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
local check_state = require "luacheck.check_state"
local core_utils = require "luacheck.core_utils"
local parse_inline_options = require "luacheck.stages.parse_inline_options"
local parser = require "luacheck.parser"
local stages = require "luacheck.stages"
local utils = require "luacheck.utils"
 
local inline_option_fields = utils.array_to_set(parse_inline_options.inline_option_fields)
 
local function validate_fields(tables, per_code_fields)
   for _, t in ipairs(tables) do
      local fields_set
 
      if per_code_fields then
         if not t.code then
            error("Warning has no code", 0)
         end
 
         local warning_info = stages.warnings[t.code]
 
         if not warning_info then
            error("Unknown issue code " .. t.code, 0)
         end
 
         fields_set = warning_info.fields_set
      else
         fields_set = inline_option_fields
      end
 
      for field in pairs(t) do
         if not fields_set[field] then
            error("Unknown field " .. field .. " in " ..
               (per_code_fields and "issue with code " .. t.code or "inline option table"), 0)
         end
      end
   end
end
 
--- Checks source.
-- Returns a table with results, with the following fields:
--    `events`: array of issues and inline option events (options, push, or pop).
--    `per_line_options`: map from line numbers to arrays of inline option events.
--    `line_lengths`: map from line numbers to line lengths.
--    `line_endings`: map from line numbers to "comment", "string", or `nil` base on
--                    whether the line ending is within a token.
-- If `events` array contains a syntax error, the other fields are empty tables.
local function check(source)
   local chstate = check_state.new(source)
   local ok, error_wrapper = utils.try(stages.run, chstate)
   local warnings, inline_options, line_lengths, line_endings
 
   if ok then
      warnings = chstate.warnings
      core_utils.sort_by_location(warnings)
      inline_options = chstate.inline_options
      line_lengths = chstate.line_lengths
      line_endings = chstate.line_endings
   else
      local err = error_wrapper.err
 
      if not utils.is_instance(err, parser.SyntaxError) then
         error(error_wrapper, 0)
      end
 
      local syntax_error = {
         code = "011",
         line = err.line,
         column = chstate:offset_to_column(err.line, err.offset),
         end_column = chstate:offset_to_column(err.line, err.end_offset),
         msg = err.msg
      }
 
      if err.prev_line then
         syntax_error.prev_line = err.prev_line
         syntax_error.prev_column = chstate:offset_to_column(err.prev_line, err.prev_offset)
         syntax_error.prev_end_column = chstate:offset_to_column(err.prev_line, err.prev_end_offset)
      end
 
      warnings = {syntax_error}
      inline_options = {}
      line_lengths = {}
      line_endings = {}
   end
 
   validate_fields(warnings, true)
   validate_fields(inline_options)
 
   return {
      warnings = warnings,
      inline_options = inline_options,
      line_lengths = line_lengths,
      line_endings = line_endings
   }
end
 
return check