From 4a3ab6e040119c140eb7111d4f06912760846003 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:37:54 +0100 Subject: [PATCH 1/2] feat(server): Add get inverted selection for quote ranges --- server/utils/quotes.go | 41 +++++++++++++++++++++++++ server/utils/quotes_test.go | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/server/utils/quotes.go b/server/utils/quotes.go index f7155ac..6e024be 100644 --- a/server/utils/quotes.go +++ b/server/utils/quotes.go @@ -33,6 +33,47 @@ func (q quoteRanges) GetQuoteForIndex(index int) *quoteRange { return &q[index] } +func (q quoteRanges) GetInvertedRanges(textLength int) [][2]int { + if textLength == 0 { + return nil + } + + if len(q) == 0 { + return [][2]int{ + { + 0, + textLength - 1, + }, + } + } + + inverted := make([][2]int, 0, len(q)) + + firstRange := q[0] + + if firstRange[0] != 0 { + inverted = append(inverted, [2]int{0, firstRange[0]}) + } + + if len(q) == 1 { + return inverted + } + + for index, currentRange := range q[:len(q)-1] { + nextRange := q[index+1] + + inverted = append(inverted, [2]int{currentRange[1] + 1, nextRange[0]}) + } + + lastRange := q[len(q)-1] + + if lastRange[1] != (textLength - 1) { + inverted = append(inverted, [2]int{lastRange[1], textLength - 1}) + } + + return inverted +} + func GetQuoteRanges(s string) quoteRanges { quoteRanges := make(quoteRanges, 0, 2) inQuote := false diff --git a/server/utils/quotes_test.go b/server/utils/quotes_test.go index 929ae0d..764e6f2 100644 --- a/server/utils/quotes_test.go +++ b/server/utils/quotes_test.go @@ -21,3 +21,63 @@ func TestQuotesEscapedQuotes( t.Fatalf("Unexpected quote ranges: %v", quoteRanges) } } + +func TestInvertedQuotesSimple( + t *testing.T, +) { + text := `"hello" "world"` + quoteRanges := GetQuoteRanges(text) + inverted := quoteRanges.GetInvertedRanges(len(text)) + + if !(len(inverted) == 1 && inverted[0][0] == 7 && inverted[0][1] == 8) { + t.Fatalf("Unexpected inverted quote ranges: %v", inverted) + } +} + +func TestInvertedQuotesImmediatelyFollowing( + t *testing.T, +) { + text := `"hello""world"` + quoteRanges := GetQuoteRanges(text) + inverted := quoteRanges.GetInvertedRanges(len(text)) + + if !(len(inverted) == 1 && inverted[0][0] == 7 && inverted[0][1] == 7) { + t.Fatalf("Unexpected inverted quote ranges: %v", inverted) + } +} + +func TestInvertedQuotesEscapedQuotes( + t *testing.T, +) { + text := `hello \"world\"` + quoteRanges := GetQuoteRanges(text) + inverted := quoteRanges.GetInvertedRanges(len(text)) + + if !(len(inverted) == 1 && inverted[0][0] == 0 && inverted[0][1] == 14) { + t.Fatalf("Unexpected inverted quote ranges: %v", inverted) + } +} + +func TestInvertedQuotesMultiple( + t *testing.T, +) { + text := `"hello" "world" "hello"` + quoteRanges := GetQuoteRanges(text) + inverted := quoteRanges.GetInvertedRanges(len(text)) + + if !(len(inverted) == 2 && inverted[0][0] == 7 && inverted[0][1] == 8 && inverted[1][0] == 15 && inverted[1][1] == 16) { + t.Fatalf("Unexpected inverted quote ranges: %v", inverted) + } +} + +func TestInvertedQuotesFullyQuoted( + t *testing.T, +) { + text := `"hello world"` + quoteRanges := GetQuoteRanges(text) + inverted := quoteRanges.GetInvertedRanges(len(text)) + + if !(len(inverted) == 0) { + t.Fatalf("Unexpected inverted quote ranges: %v", inverted) + } +} From ea667653cd0ecc2aabbbd8080824bf7aa534bd72 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Fri, 29 Nov 2024 19:04:47 +0100 Subject: [PATCH 2/2] fix(server): Improve quotes --- server/handlers/ssh_config/analyzer/quotes.go | 19 +++++++++++-------- .../ssh_config/analyzer/quotes_test.go | 3 ++- .../handlers/sshd_config/analyzer/quotes.go | 9 ++------- server/utils/quotes.go | 14 ++++++-------- server/utils/quotes_test.go | 12 ++++++++++++ 5 files changed, 33 insertions(+), 24 deletions(-) diff --git a/server/handlers/ssh_config/analyzer/quotes.go b/server/handlers/ssh_config/analyzer/quotes.go index 2155fe9..50a3399 100644 --- a/server/handlers/ssh_config/analyzer/quotes.go +++ b/server/handlers/ssh_config/analyzer/quotes.go @@ -27,15 +27,18 @@ func checkIsUsingDoubleQuotes( valueRange common.LocationRange, ) { quoteRanges := utils.GetQuoteRanges(value.Raw) - singleQuotePosition := strings.Index(value.Raw, "'") + invertedRanges := quoteRanges.GetInvertedRanges(len(value.Raw)) - // Single quote - if singleQuotePosition != -1 && !quoteRanges.IsIndexInsideQuotes(singleQuotePosition) { - ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{ - Range: valueRange.ToLSPRange(), - Message: "ssh_config does not support single quotes. Use double quotes (\") instead.", - Severity: &common.SeverityError, - }) + for _, rang := range invertedRanges { + text := value.Raw[rang[0]:rang[1]] + + if strings.Contains(text, "'") { + ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{ + Range: valueRange.ToLSPRange(), + Message: "ssh_config does not support single quotes. Use double quotes (\") instead.", + Severity: &common.SeverityError, + }) + } } } diff --git a/server/handlers/ssh_config/analyzer/quotes_test.go b/server/handlers/ssh_config/analyzer/quotes_test.go index accb08a..c52a218 100644 --- a/server/handlers/ssh_config/analyzer/quotes_test.go +++ b/server/handlers/ssh_config/analyzer/quotes_test.go @@ -101,7 +101,8 @@ func TestValidDependentOptionsExample( d := testutils_test.DocumentFromInput(t, ` Port 1234 CanonicalizeHostname yes -CanonicalDomains example.com +CanonicalDomains "example.com" +Test "hello world 'test' " `) ctx := &analyzerContext{ document: d, diff --git a/server/handlers/sshd_config/analyzer/quotes.go b/server/handlers/sshd_config/analyzer/quotes.go index 7dbf275..a563bc5 100644 --- a/server/handlers/sshd_config/analyzer/quotes.go +++ b/server/handlers/sshd_config/analyzer/quotes.go @@ -3,7 +3,6 @@ package analyzer import ( "config-lsp/common" commonparser "config-lsp/common/parser" - "config-lsp/utils" "strings" protocol "github.com/tliron/glsp/protocol_3_16" @@ -26,14 +25,10 @@ func checkIsUsingDoubleQuotes( value commonparser.ParsedString, valueRange common.LocationRange, ) { - quoteRanges := utils.GetQuoteRanges(value.Raw) - singleQuotePosition := strings.Index(value.Raw, "'") - - // Single quote - if singleQuotePosition != -1 && !quoteRanges.IsIndexInsideQuotes(singleQuotePosition) { + if strings.HasPrefix(value.Raw, "'") && strings.HasSuffix(value.Raw, "'") { ctx.diagnostics = append(ctx.diagnostics, protocol.Diagnostic{ Range: valueRange.ToLSPRange(), - Message: "sshd_config does not support single quotes. Use double quotes (\") instead.", + Message: "ssh_config does not support single quotes. Use double quotes (\") instead.", Severity: &common.SeverityError, }) } diff --git a/server/utils/quotes.go b/server/utils/quotes.go index 6e024be..3badaca 100644 --- a/server/utils/quotes.go +++ b/server/utils/quotes.go @@ -55,20 +55,18 @@ func (q quoteRanges) GetInvertedRanges(textLength int) [][2]int { inverted = append(inverted, [2]int{0, firstRange[0]}) } - if len(q) == 1 { - return inverted - } - - for index, currentRange := range q[:len(q)-1] { - nextRange := q[index+1] + if len(q) > 1 { + for index, currentRange := range q[:len(q)-1] { + nextRange := q[index+1] - inverted = append(inverted, [2]int{currentRange[1] + 1, nextRange[0]}) + inverted = append(inverted, [2]int{currentRange[1] + 1, nextRange[0]}) + } } lastRange := q[len(q)-1] if lastRange[1] != (textLength - 1) { - inverted = append(inverted, [2]int{lastRange[1], textLength - 1}) + inverted = append(inverted, [2]int{lastRange[1] + 1, textLength}) } return inverted diff --git a/server/utils/quotes_test.go b/server/utils/quotes_test.go index 764e6f2..86fe71a 100644 --- a/server/utils/quotes_test.go +++ b/server/utils/quotes_test.go @@ -81,3 +81,15 @@ func TestInvertedQuotesFullyQuoted( t.Fatalf("Unexpected inverted quote ranges: %v", inverted) } } + +func TestInvertedQuotesFirstThenRemaining( + t *testing.T, +) { + text := `"hello world" i am here` + quoteRanges := GetQuoteRanges(text) + inverted := quoteRanges.GetInvertedRanges(len(text)) + + if !(len(inverted) == 1 && inverted[0][0] == 13 && inverted[0][1] == 23) { + t.Fatalf("Unexpected inverted quote ranges: %v", inverted) + } +}