Skip to content

Commit

Permalink
feat(ssh_config): Add first version of ssh_config
Browse files Browse the repository at this point in the history
  • Loading branch information
Myzel394 committed Sep 22, 2024
1 parent 846851d commit fc0dca8
Show file tree
Hide file tree
Showing 31 changed files with 2,808 additions and 131 deletions.
45 changes: 45 additions & 0 deletions handlers/ssh_config/ast/error-listener.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ast

import (
"config-lsp/common"

"github.com/antlr4-go/antlr/v4"
)

type errorListenerContext struct {
line uint32
}

type errorListener struct {
*antlr.DefaultErrorListener
Errors []common.LSPError
context errorListenerContext
}

func (d *errorListener) SyntaxError(
recognizer antlr.Recognizer,
offendingSymbol interface{},
_ int,
character int,
message string,
error antlr.RecognitionException,
) {
line := d.context.line
d.Errors = append(d.Errors, common.LSPError{
Range: common.CreateSingleCharRange(uint32(line), uint32(character)),
Err: common.SyntaxError{
Message: message,
},
})
}

func createErrorListener(
line uint32,
) errorListener {
return errorListener{
Errors: make([]common.LSPError, 0),
context: errorListenerContext{
line: line,
},
}
}
35 changes: 35 additions & 0 deletions handlers/ssh_config/ast/indexes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ast

import "config-lsp/common"


type ValidPath string

func (v ValidPath) AsURI() string {
return "file://" + string(v)
}

type SSHIndexIncludeValue struct {
common.LocationRange
Value string

// Actual valid paths, these will be set by the analyzer
Paths []ValidPath
}

type SSHIndexIncludeLine struct {
Values []*SSHIndexIncludeValue
Option *SSHOption
Block *SSHBlock
}

type SSHIndexes struct {
Includes []*SSHIndexIncludeLine
}

func NewSSHIndexes() *SSHIndexes {
return &SSHIndexes{
Includes: make([]*SSHIndexIncludeLine, 0),
}
}

171 changes: 171 additions & 0 deletions handlers/ssh_config/ast/listener.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package ast

import (
"config-lsp/common"
commonparser "config-lsp/common/parser"
"config-lsp/handlers/ssh_config/ast/parser"
"config-lsp/handlers/ssh_config/match-parser"
"strings"

"github.com/emirpasic/gods/maps/treemap"
gods "github.com/emirpasic/gods/utils"
)

type sshListenerContext struct {
line uint32
currentOption *SSHOption
currentBlock SSHBlock
currentKeyIsBlockOf *SSHBlockType
currentIndexes *SSHIndexes
}

func createListenerContext() *sshListenerContext {
context := new(sshListenerContext)
context.currentIndexes = NewSSHIndexes()

return context
}

func createListener(
config *SSHConfig,
context *sshListenerContext,
) sshParserListener {
return sshParserListener{
Config: config,
Errors: make([]common.LSPError, 0),
sshContext: context,
}
}

type sshParserListener struct {
*parser.BaseConfigListener
Config *SSHConfig
Errors []common.LSPError
sshContext *sshListenerContext
}

func (s *sshParserListener) EnterEntry(ctx *parser.EntryContext) {
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
location.ChangeBothLines(s.sshContext.line)

value := commonparser.ParseRawString(ctx.GetText(), commonparser.FullFeatures)
option := &SSHOption{
LocationRange: location,
Value: value,
}

s.sshContext.currentOption = option
}

func (s *sshParserListener) EnterKey(ctx *parser.KeyContext) {
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
location.ChangeBothLines(s.sshContext.line)

text := ctx.GetText()
value := commonparser.ParseRawString(text, commonparser.FullFeatures)
key := strings.Trim(
value.Value,
" ",
)

switch strings.ToLower(text) {
case "match":
value := SSHBlockTypeMatch
s.sshContext.currentKeyIsBlockOf = &value
case "host":
value := SSHBlockTypeHost
s.sshContext.currentKeyIsBlockOf = &value
}

s.sshContext.currentOption.Key = &SSHKey{
LocationRange: location,
Value: value,
Key: key,
}
}

func (s *sshParserListener) EnterSeparator(ctx *parser.SeparatorContext) {
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
location.ChangeBothLines(s.sshContext.line)

text := ctx.GetText()
value := commonparser.ParseRawString(text, commonparser.FullFeatures)

s.sshContext.currentOption.Separator = &SSHSeparator{
LocationRange: location,
Value: value,
}
}

func (s *sshParserListener) EnterValue(ctx *parser.ValueContext) {
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
location.ChangeBothLines(s.sshContext.line)

value := commonparser.ParseRawString(ctx.GetText(), commonparser.FullFeatures)
s.sshContext.currentOption.OptionValue = &SSHValue{
LocationRange: location,
Value: value,
}
}

func (s *sshParserListener) ExitEntry(ctx *parser.EntryContext) {
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
location.ChangeBothLines(s.sshContext.line)

defer (func() {
s.sshContext.currentOption = nil
})()

if s.sshContext.currentKeyIsBlockOf != nil {
switch *s.sshContext.currentKeyIsBlockOf {
case SSHBlockTypeMatch:
var match *matchparser.Match

matchParser := matchparser.NewMatch()
errors := matchParser.Parse(
s.sshContext.currentOption.OptionValue.Value.Raw,
location.Start.Line,
s.sshContext.currentOption.OptionValue.Start.Character,
)

if len(errors) > 0 {
for _, err := range errors {
s.Errors = append(s.Errors, common.LSPError{
Range: err.Range.ShiftHorizontal(s.sshContext.currentOption.Start.Character),
Err: err.Err,
})
}
} else {
match = matchParser
}

matchBlock := &SSHMatchBlock{
LocationRange: location,
MatchOption: s.sshContext.currentOption,
MatchValue: match,
Options: treemap.NewWith(gods.UInt32Comparator),
}

s.Config.Options.Put(
location.Start.Line,
matchBlock,
)

s.sshContext.currentKeyIsBlockOf = nil
s.sshContext.currentBlock = matchBlock
}

return
}

if s.sshContext.currentBlock == nil {
s.Config.Options.Put(
location.Start.Line,
s.sshContext.currentOption,
)
} else {
block := s.sshContext.currentBlock
block.AddOption(s.sshContext.currentOption)
block.SetEnd(location.End)
}
}
85 changes: 85 additions & 0 deletions handlers/ssh_config/ast/parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package ast

import (
"config-lsp/common"
"config-lsp/handlers/ssh_config/ast/parser"
"config-lsp/utils"
"regexp"

"github.com/antlr4-go/antlr/v4"
"github.com/emirpasic/gods/maps/treemap"

gods "github.com/emirpasic/gods/utils"
)

func NewSSHConfig() *SSHConfig {
config := &SSHConfig{}
config.Clear()

return config
}

func (c *SSHConfig) Clear() {
c.Options = treemap.NewWith(gods.UInt32Comparator)
c.CommentLines = map[uint32]struct{}{}
}

var commentPattern = regexp.MustCompile(`^\s*#.*$`)
var emptyPattern = regexp.MustCompile(`^\s*$`)

func (c *SSHConfig) Parse(input string) []common.LSPError {
errors := make([]common.LSPError, 0)
lines := utils.SplitIntoLines(input)
context := createListenerContext()

for rawLineNumber, line := range lines {
context.line = uint32(rawLineNumber)

if emptyPattern.MatchString(line) {
continue
}

if commentPattern.MatchString(line) {
c.CommentLines[context.line] = struct{}{}
continue
}

errors = append(
errors,
c.parseStatement(context, line)...,
)
}

return errors
}

func (c *SSHConfig) parseStatement(
context *sshListenerContext,
input string,
) []common.LSPError {
stream := antlr.NewInputStream(input)

lexerErrorListener := createErrorListener(context.line)
lexer := parser.NewConfigLexer(stream)
lexer.RemoveErrorListeners()
lexer.AddErrorListener(&lexerErrorListener)

tokenStream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)

parserErrorListener := createErrorListener(context.line)
antlrParser := parser.NewConfigParser(tokenStream)
antlrParser.RemoveErrorListeners()
antlrParser.AddErrorListener(&parserErrorListener)

listener := createListener(c, context)
antlr.ParseTreeWalkerDefault.Walk(
&listener,
antlrParser.LineStatement(),
)

errors := lexerErrorListener.Errors
errors = append(errors, parserErrorListener.Errors...)
errors = append(errors, listener.Errors...)

return errors
}
5 changes: 4 additions & 1 deletion handlers/ssh_config/ast/parser/Config.interp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ null
null
null
null
null

token symbolic names:
null
HASH
WHITESPACE
STRING
NEWLINE
QUOTED_STRING

rule names:
lineStatement
Expand All @@ -19,7 +21,8 @@ separator
key
value
leadingComment
string


atn:
[4, 1, 4, 66, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 1, 0, 1, 0, 1, 0, 3, 0, 16, 8, 0, 3, 0, 18, 8, 0, 1, 0, 1, 0, 1, 1, 3, 1, 23, 8, 1, 1, 1, 3, 1, 26, 8, 1, 1, 1, 3, 1, 29, 8, 1, 1, 1, 3, 1, 32, 8, 1, 1, 1, 3, 1, 35, 8, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 5, 4, 43, 8, 4, 10, 4, 12, 4, 46, 9, 4, 1, 4, 3, 4, 49, 8, 4, 1, 4, 3, 4, 52, 8, 4, 1, 5, 1, 5, 3, 5, 56, 8, 5, 1, 5, 1, 5, 3, 5, 60, 8, 5, 4, 5, 62, 8, 5, 11, 5, 12, 5, 63, 1, 5, 0, 0, 6, 0, 2, 4, 6, 8, 10, 0, 0, 73, 0, 17, 1, 0, 0, 0, 2, 22, 1, 0, 0, 0, 4, 36, 1, 0, 0, 0, 6, 38, 1, 0, 0, 0, 8, 44, 1, 0, 0, 0, 10, 53, 1, 0, 0, 0, 12, 18, 3, 2, 1, 0, 13, 18, 3, 10, 5, 0, 14, 16, 5, 2, 0, 0, 15, 14, 1, 0, 0, 0, 15, 16, 1, 0, 0, 0, 16, 18, 1, 0, 0, 0, 17, 12, 1, 0, 0, 0, 17, 13, 1, 0, 0, 0, 17, 15, 1, 0, 0, 0, 18, 19, 1, 0, 0, 0, 19, 20, 5, 0, 0, 1, 20, 1, 1, 0, 0, 0, 21, 23, 5, 2, 0, 0, 22, 21, 1, 0, 0, 0, 22, 23, 1, 0, 0, 0, 23, 25, 1, 0, 0, 0, 24, 26, 3, 6, 3, 0, 25, 24, 1, 0, 0, 0, 25, 26, 1, 0, 0, 0, 26, 28, 1, 0, 0, 0, 27, 29, 3, 4, 2, 0, 28, 27, 1, 0, 0, 0, 28, 29, 1, 0, 0, 0, 29, 31, 1, 0, 0, 0, 30, 32, 3, 8, 4, 0, 31, 30, 1, 0, 0, 0, 31, 32, 1, 0, 0, 0, 32, 34, 1, 0, 0, 0, 33, 35, 3, 10, 5, 0, 34, 33, 1, 0, 0, 0, 34, 35, 1, 0, 0, 0, 35, 3, 1, 0, 0, 0, 36, 37, 5, 2, 0, 0, 37, 5, 1, 0, 0, 0, 38, 39, 5, 3, 0, 0, 39, 7, 1, 0, 0, 0, 40, 41, 5, 3, 0, 0, 41, 43, 5, 2, 0, 0, 42, 40, 1, 0, 0, 0, 43, 46, 1, 0, 0, 0, 44, 42, 1, 0, 0, 0, 44, 45, 1, 0, 0, 0, 45, 48, 1, 0, 0, 0, 46, 44, 1, 0, 0, 0, 47, 49, 5, 3, 0, 0, 48, 47, 1, 0, 0, 0, 48, 49, 1, 0, 0, 0, 49, 51, 1, 0, 0, 0, 50, 52, 5, 2, 0, 0, 51, 50, 1, 0, 0, 0, 51, 52, 1, 0, 0, 0, 52, 9, 1, 0, 0, 0, 53, 55, 5, 1, 0, 0, 54, 56, 5, 2, 0, 0, 55, 54, 1, 0, 0, 0, 55, 56, 1, 0, 0, 0, 56, 61, 1, 0, 0, 0, 57, 59, 5, 3, 0, 0, 58, 60, 5, 2, 0, 0, 59, 58, 1, 0, 0, 0, 59, 60, 1, 0, 0, 0, 60, 62, 1, 0, 0, 0, 61, 57, 1, 0, 0, 0, 62, 63, 1, 0, 0, 0, 63, 61, 1, 0, 0, 0, 63, 64, 1, 0, 0, 0, 64, 11, 1, 0, 0, 0, 13, 15, 17, 22, 25, 28, 31, 34, 44, 48, 51, 55, 59, 63]
[4, 1, 5, 71, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 1, 0, 1, 0, 1, 0, 3, 0, 18, 8, 0, 3, 0, 20, 8, 0, 1, 0, 1, 0, 1, 1, 3, 1, 25, 8, 1, 1, 1, 3, 1, 28, 8, 1, 1, 1, 3, 1, 31, 8, 1, 1, 1, 3, 1, 34, 8, 1, 1, 1, 3, 1, 37, 8, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 5, 4, 46, 8, 4, 10, 4, 12, 4, 49, 9, 4, 1, 4, 3, 4, 52, 8, 4, 1, 4, 3, 4, 55, 8, 4, 1, 5, 1, 5, 3, 5, 59, 8, 5, 1, 5, 1, 5, 3, 5, 63, 8, 5, 4, 5, 65, 8, 5, 11, 5, 12, 5, 66, 1, 6, 1, 6, 1, 6, 0, 0, 7, 0, 2, 4, 6, 8, 10, 12, 0, 1, 2, 0, 3, 3, 5, 5, 77, 0, 19, 1, 0, 0, 0, 2, 24, 1, 0, 0, 0, 4, 38, 1, 0, 0, 0, 6, 40, 1, 0, 0, 0, 8, 47, 1, 0, 0, 0, 10, 56, 1, 0, 0, 0, 12, 68, 1, 0, 0, 0, 14, 20, 3, 2, 1, 0, 15, 20, 3, 10, 5, 0, 16, 18, 5, 2, 0, 0, 17, 16, 1, 0, 0, 0, 17, 18, 1, 0, 0, 0, 18, 20, 1, 0, 0, 0, 19, 14, 1, 0, 0, 0, 19, 15, 1, 0, 0, 0, 19, 17, 1, 0, 0, 0, 20, 21, 1, 0, 0, 0, 21, 22, 5, 0, 0, 1, 22, 1, 1, 0, 0, 0, 23, 25, 5, 2, 0, 0, 24, 23, 1, 0, 0, 0, 24, 25, 1, 0, 0, 0, 25, 27, 1, 0, 0, 0, 26, 28, 3, 6, 3, 0, 27, 26, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 30, 1, 0, 0, 0, 29, 31, 3, 4, 2, 0, 30, 29, 1, 0, 0, 0, 30, 31, 1, 0, 0, 0, 31, 33, 1, 0, 0, 0, 32, 34, 3, 8, 4, 0, 33, 32, 1, 0, 0, 0, 33, 34, 1, 0, 0, 0, 34, 36, 1, 0, 0, 0, 35, 37, 3, 10, 5, 0, 36, 35, 1, 0, 0, 0, 36, 37, 1, 0, 0, 0, 37, 3, 1, 0, 0, 0, 38, 39, 5, 2, 0, 0, 39, 5, 1, 0, 0, 0, 40, 41, 3, 12, 6, 0, 41, 7, 1, 0, 0, 0, 42, 43, 3, 12, 6, 0, 43, 44, 5, 2, 0, 0, 44, 46, 1, 0, 0, 0, 45, 42, 1, 0, 0, 0, 46, 49, 1, 0, 0, 0, 47, 45, 1, 0, 0, 0, 47, 48, 1, 0, 0, 0, 48, 51, 1, 0, 0, 0, 49, 47, 1, 0, 0, 0, 50, 52, 3, 12, 6, 0, 51, 50, 1, 0, 0, 0, 51, 52, 1, 0, 0, 0, 52, 54, 1, 0, 0, 0, 53, 55, 5, 2, 0, 0, 54, 53, 1, 0, 0, 0, 54, 55, 1, 0, 0, 0, 55, 9, 1, 0, 0, 0, 56, 58, 5, 1, 0, 0, 57, 59, 5, 2, 0, 0, 58, 57, 1, 0, 0, 0, 58, 59, 1, 0, 0, 0, 59, 64, 1, 0, 0, 0, 60, 62, 3, 12, 6, 0, 61, 63, 5, 2, 0, 0, 62, 61, 1, 0, 0, 0, 62, 63, 1, 0, 0, 0, 63, 65, 1, 0, 0, 0, 64, 60, 1, 0, 0, 0, 65, 66, 1, 0, 0, 0, 66, 64, 1, 0, 0, 0, 66, 67, 1, 0, 0, 0, 67, 11, 1, 0, 0, 0, 68, 69, 7, 0, 0, 0, 69, 13, 1, 0, 0, 0, 13, 17, 19, 24, 27, 30, 33, 36, 47, 51, 54, 58, 62, 66]
1 change: 1 addition & 0 deletions handlers/ssh_config/ast/parser/Config.tokens
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ HASH=1
WHITESPACE=2
STRING=3
NEWLINE=4
QUOTED_STRING=5
'#'=1
Loading

0 comments on commit fc0dca8

Please sign in to comment.