Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The set pattern for single range char is not working in glob #2754

Open
tomlau10 opened this issue Jul 13, 2024 · 2 comments
Open

The set pattern for single range char is not working in glob #2754

tomlau10 opened this issue Jul 13, 2024 · 2 comments

Comments

@tomlau10
Copy link
Contributor

tomlau10 commented Jul 13, 2024

How are you using the lua-language-server?

Visual Studio Code Extension (sumneko.lua)

Which OS are you using?

Windows

What is the issue affecting?

Diagnostics/Syntax Checking

Expected Behaviour

I am testing the glob like pattern used in Lua.doc.<scope>Name, and the set pattern seems not working for single character.

  • .luarc.jsonc
{
    "doc.privateName": [
        "_[aeiouA-Z]"   // underscore followed by any upper letter, or lower letters a|e|i|o|u
    ]
}
  • test.lua
---@class A
local A = {}
A._A = 1
A._Z = 1
A._a = 1
A._e = 1
A._z = 1
A._AA = 1
A._aa = 1

---@type A
local t = {}
print(t._A)     -- warning
print(t._Z)     -- warning
print(t._a)     -- warning
print(t._e)     -- warning
print(t._z)     -- ok
print(t._AA)    -- ok
print(t._aa)    -- ok

Actual Behaviour

---@type A
local t = {}
print(t._A)     -- warning
print(t._Z)     -- warning
print(t._a)     -- ok (false negative)
print(t._e)     -- ok (false negative)
print(t._z)     -- ok
print(t._AA)    -- ok
print(t._aa)    -- ok
  • the single range word aeiou is not working as expected

Reproduction steps

Use the provided snippet

Additional Notes

I know that the glob pattern syntax in defined using LPeg:

local parser = m.P {
'Main',
['Sp'] = m.S(' \t')^0,
['Slash'] = m.P('/')^1,
['Main'] = m.Ct(m.V'Sp' * m.P'{' * m.V'Pattern' * (',' * expect(m.V'Pattern', 'Miss exp after ","'))^0 * m.P'}')
+ m.Ct(m.V'Pattern')
+ m.T'Main Failed'
,
['Pattern'] = m.Ct(m.V'Sp' * prop('neg', m.P'!') * expect(m.V'Unit', 'Miss exp after "!"'))
+ m.Ct(m.V'Unit')
,
['NeedRoot'] = prop('root', (m.P'.' * m.V'Slash' + m.V'Slash')),
['Unit'] = m.V'Sp' * m.V'NeedRoot'^-1 * expect(m.V'Exp', 'Miss exp') * m.V'Sp',
['Exp'] = m.V'Sp' * (m.V'FSymbol' + object('/', m.V'Slash') + m.V'Word')^0 * m.V'Sp',
['Word'] = object('word', m.Ct((m.V'CSymbol' + m.V'Char' - m.V'FSymbol')^1)),
['CSymbol'] = object('*', m.P'*')
+ object('?', m.P'?')
+ object('[]', m.V'Range')
,
['SimpleChar'] = m.P(1) - m.S',{}[]*?/',
['EscChar'] = m.P'\\' / '' * m.P(1),
['Char'] = object('char', m.Cs((m.V'EscChar' + m.V'SimpleChar')^1)),
['FSymbol'] = object('**', m.P'**'),
['RangeWord'] = 1 - m.P']',
['Range'] = m.P'[' * m.Ct(m.V'RangeUnit'^0) * m.P']'^-1,
['RangeUnit'] = m.Ct(m.C(m.V'RangeWord') * m.P'-' * m.C(m.V'RangeWord'))
+ m.V'RangeWord',
}

I am not familiar with LPeg, but by adding a print(#range, range[1], range[2]) inside mt:range() here, those single range word seems don't even get parsed. 😕
for _, range in ipairs(exp.value) do
if #range == 1 then

With a bit of testing, the RangeUnit definition seems should be changed from:

    ['RangeUnit']   = m.Ct(m.C(m.V'RangeWord') * m.P'-' * m.C(m.V'RangeWord'))
                    + m.V'RangeWord',

to =>

    ['RangeUnit']   = m.Ct(m.C(m.V'RangeWord') * m.P'-' * m.C(m.V'RangeWord'))
                    + m.Ct(m.C(m.V'RangeWord')),

Then the set logic for single range character starts to work 🎉
But I don't know why it works this way 🙈


Can anyone comment on my above suggested change?
If this is correct, I am going to open a PR. 🙂

Log File

No response

@tomlau10 tomlau10 changed the title The set pattern for **single range char** is not working in glob The set pattern for single range char is not working in glob Jul 13, 2024
@tomlau10
Copy link
Contributor Author

More issues found 😕

{
    "doc.privateName": [
        "_*[a-zA-Z0-9]"     // prefix with at least 1 _, followed by anything, then end with a char
    ]
}
  • this is expected to match _id / _id_1 / __id but no, it gives false negative
---@class A
local A = {}
A._a = 0
A._a1 = 0
A.__a = 0
A.__a1 = 0

---@type A
local t = {}
print(t._a)     -- warning
print(t._a1)    -- ok (false negative)
print(t.__a)    -- warning
print(t.__a1)   -- ok (false negative)

By testing the glob pattern here, all of the above should be matched:
https://www.digitalocean.com/community/tools/glob?comments=true&glob=_%2A%5Ba-zA-Z0-9%5D&matches=false&tests=_a&tests=_a1&tests=__a&tests=__a1

@sumneko
Copy link
Collaborator

sumneko commented Aug 15, 2024

Perhaps I should go and find a third-party library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants