• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

alerque / luacheck / 10600181429

28 Aug 2024 03:54PM UTC coverage: 97.063% (-0.01%) from 97.077%
10600181429

push

github

alerque
chore: Correct availability of clobals in reader/writers

3 of 3 new or added lines in 1 file covered. (100.0%)

5 existing lines in 4 files now uncovered.

6312 of 6503 relevant lines covered (97.06%)

23960.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.5
/src/luacheck/globbing.lua
1
local fs = require "luacheck.fs"
508✔
2
local utils = require "luacheck.utils"
508✔
3

4
-- Only ?, *, ** and simple character classes (with ranges and negation) are supported.
5
-- Hidden files are not treated specially. Special characters can't be escaped.
6
local globbing = {}
508✔
7

8
local function is_regular_path(glob)
9
   return not glob:find("[*?%[]")
7,728✔
10
end
11

12
local function get_parts(path)
13
   local parts = {}
14,264✔
14

15
   for part in path:gmatch("[^"..utils.dir_sep.."]+") do
111,528✔
16
      table.insert(parts, part)
97,264✔
17
   end
18

19
   return parts
14,264✔
20
end
21

22
local function glob_pattern_escaper(c)
23
   return ((c == "*" or c == "?") and "." or "%")..c
39,620✔
24
end
25

26
local function glob_range_escaper(c)
27
   return c == "-" and c or ("%"..c)
28✔
28
end
29

30
local function glob_part_to_pattern(glob_part)
31
   local buffer = {"^"}
59,408✔
32
   local i = 1
59,408✔
33

34
   while i <= #glob_part do
118,852✔
35
      local bracketless
36
      bracketless, i = glob_part:match("([^%[]*)()", i)
59,444✔
37
      table.insert(buffer, (bracketless:gsub("%p", glob_pattern_escaper)))
59,444✔
38

39
      if glob_part:sub(i, i) == "[" then
59,444✔
40
         table.insert(buffer, "[")
84✔
41
         i = i + 1
84✔
42
         local first_char = glob_part:sub(i, i)
84✔
43

44
         if first_char == "!" then
84✔
45
            table.insert(buffer, "^")
28✔
46
            i = i + 1
28✔
47
         elseif first_char == "]" then
56✔
48
            table.insert(buffer, "%]")
20✔
49
            i = i + 1
20✔
50
         end
51

52
         bracketless, i = glob_part:match("([^%]]*)()", i)
84✔
53

54
         if bracketless:sub(1, 1) == "-" then
84✔
55
            table.insert(buffer, "%-")
12✔
56
            bracketless = bracketless:sub(2)
12✔
57
         end
58

59
         local last_dash = ""
84✔
60

61
         if bracketless:sub(-1) == "-" then
84✔
62
            last_dash = "-"
4✔
63
            bracketless = bracketless:sub(1, -2)
4✔
64
         end
65

66
         table.insert(buffer, (bracketless:gsub("%p", glob_range_escaper)))
84✔
67
         table.insert(buffer, last_dash.."]")
84✔
68
         i = i + 1
84✔
69
      end
70
   end
71

72
   table.insert(buffer, "$")
59,408✔
73
   return table.concat(buffer)
59,408✔
74
end
75

76
local function part_match(glob_part, path_part)
77
   return utils.pmatch(path_part, glob_part_to_pattern(glob_part))
59,408✔
78
end
79

80
local function parts_match(glob_parts, glob_i, path_parts, path_i)
81
   local glob_part = glob_parts[glob_i]
74,648✔
82

83
   if not glob_part then
74,648✔
84
      -- Reached glob end, path matches the glob or its subdirectory.
85
      -- E.g. path "foo/bar/baz/src.lua" matches glob "foo/*/baz".
86
      return true
220✔
87
   end
88

89
   if glob_part == "**" then
74,428✔
90
      -- "**" can consume any number of path parts.
91
      for i = path_i, #path_parts + 1 do
53,904✔
92
         if parts_match(glob_parts, glob_i + 1, path_parts, i) then
46,460✔
93
            return true
132✔
94
         end
95
      end
96

97
      return false
7,444✔
98
   end
99

100
   local path_part = path_parts[path_i]
66,852✔
101
   return path_part and part_match(glob_part, path_part) and (
66,852✔
102
      parts_match(glob_parts, glob_i + 1, path_parts, path_i + 1))
66,852✔
103
end
104

105
-- Checks if a path matches a globbing pattern.
106
-- Both must be absolute.
107
function globbing.match(glob, path)
508✔
108
   if is_regular_path(glob) then
7,728✔
109
      return fs.is_subpath(glob, path)
600✔
110
   end
111

112
   local glob_base, path_base
113
   glob_base, glob = fs.split_base(glob)
7,128✔
114
   path_base, path = fs.split_base(path)
7,128✔
115

116
   if glob_base ~= path_base then
7,128✔
117
      return false
×
118
   end
119

120
   local glob_parts = get_parts(glob)
7,128✔
121
   local path_parts = get_parts(path)
7,128✔
122
   return parts_match(glob_parts, 1, path_parts, 1)
7,128✔
123
end
124

125
-- Checks if glob1 is less specific than glob2 and should be applied
126
-- first in overrides.
127
function globbing.compare(glob1, glob2)
508✔
128
   local base1, base2
129
   base1, glob1 = fs.split_base(glob1)
4✔
130
   base2, glob2 = fs.split_base(glob2)
4✔
131

132
   if base1 ~= base2 then
4✔
133
      return base1 < base2
×
134
   end
135

136
   local parts1 = get_parts(glob1)
4✔
137
   local parts2 = get_parts(glob2)
4✔
138

139
   for i = 1, math.max(#parts1, #parts2) do
32✔
140
      if not parts1[i] then
32✔
UNCOV
141
         return true
×
142
      elseif not parts2[i] then
32✔
143
         return false
4✔
144
      end
145

146
      if (parts1[i] == "**" or parts2[i] == "**") and parts1[i] ~= parts2[i] then
28✔
147
         return parts1[i] == "**"
×
148
      end
149

150
      local _, specials1 = parts1[i]:gsub("[%*%?%[]", {})
28✔
151
      local _, specials2 = parts2[i]:gsub("[%*%?%[]", {})
28✔
152

153
      if specials1 ~= specials2 then
28✔
154
         return specials1 > specials2
×
155
      end
156
   end
157

158
   return glob1 < glob2
×
159
end
160

161
return globbing
508✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc