mirror of
https://github.com/Myzel394/config-lsp.git
synced 2025-06-18 23:15:26 +02:00
feat(aliases): Add first aliases
This commit is contained in:
parent
6c3e0d9d23
commit
a5f834a38b
@ -1,6 +1,9 @@
|
||||
package common
|
||||
|
||||
import protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
import (
|
||||
"github.com/antlr4-go/antlr/v4"
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
type Location struct {
|
||||
Line uint32
|
||||
@ -63,3 +66,22 @@ func CreateSingleCharRange(line uint32, character uint32) LocationRange {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func CharacterRangeFromCtx(
|
||||
ctx antlr.BaseParserRuleContext,
|
||||
) LocationRange {
|
||||
line := uint32(ctx.GetStart().GetLine())
|
||||
start := uint32(ctx.GetStart().GetStart())
|
||||
end := uint32(ctx.GetStop().GetStop())
|
||||
|
||||
return LocationRange{
|
||||
Start: Location{
|
||||
Line: line,
|
||||
Character: start,
|
||||
},
|
||||
End: Location{
|
||||
Line: line,
|
||||
Character: end + 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
102
handlers/aliases/Aliases.g4
Normal file
102
handlers/aliases/Aliases.g4
Normal file
@ -0,0 +1,102 @@
|
||||
grammar Aliases;
|
||||
|
||||
lineStatement
|
||||
: entry SEPARATOR? comment? EOF
|
||||
;
|
||||
|
||||
entry
|
||||
: SEPARATOR? key SEPARATOR? separator SEPARATOR? values
|
||||
;
|
||||
|
||||
separator
|
||||
: COLON
|
||||
;
|
||||
|
||||
key
|
||||
: STRING
|
||||
;
|
||||
|
||||
// // Values // //
|
||||
values
|
||||
: (value COMMA SEPARATOR)* value
|
||||
;
|
||||
|
||||
value
|
||||
: (user | file | command | include | email)
|
||||
;
|
||||
|
||||
user
|
||||
: STRING
|
||||
;
|
||||
|
||||
file
|
||||
: (SLASH STRING)+ SLASH?
|
||||
;
|
||||
|
||||
command
|
||||
: VERTLINE STRING
|
||||
;
|
||||
|
||||
include
|
||||
: COLON INCLUDE COLON file
|
||||
;
|
||||
|
||||
comment
|
||||
: NUMBER_SIGN (SEPARATOR? STRING)+ SEPARATOR?
|
||||
;
|
||||
|
||||
email
|
||||
: STRING AT STRING
|
||||
;
|
||||
|
||||
error
|
||||
: errorStatus COLON errorCode SEPARATOR errorMessage
|
||||
;
|
||||
|
||||
errorStatus
|
||||
: STRING
|
||||
;
|
||||
|
||||
errorCode
|
||||
: STRING
|
||||
;
|
||||
|
||||
errorMessage
|
||||
: STRING
|
||||
;
|
||||
|
||||
SEPARATOR
|
||||
: [ \t]+
|
||||
;
|
||||
|
||||
AT
|
||||
: '@'
|
||||
;
|
||||
|
||||
INCLUDE
|
||||
: 'i' 'n' 'c' 'l' 'u' 'd' 'e'
|
||||
;
|
||||
|
||||
VERTLINE
|
||||
: '|'
|
||||
;
|
||||
|
||||
COLON
|
||||
: ':'
|
||||
;
|
||||
|
||||
COMMA
|
||||
: ','
|
||||
;
|
||||
|
||||
NUMBER_SIGN
|
||||
: '#'
|
||||
;
|
||||
|
||||
SLASH
|
||||
: '/'
|
||||
;
|
||||
|
||||
STRING
|
||||
: ~(' ' | '\t' | '\n' | '\r' | ':' | ',' | '#' | '@' | '|' | '/')+
|
||||
;
|
45
handlers/aliases/parser/Aliases.interp
Normal file
45
handlers/aliases/parser/Aliases.interp
Normal file
@ -0,0 +1,45 @@
|
||||
token literal names:
|
||||
null
|
||||
null
|
||||
'@'
|
||||
null
|
||||
'|'
|
||||
':'
|
||||
','
|
||||
'#'
|
||||
'/'
|
||||
null
|
||||
|
||||
token symbolic names:
|
||||
null
|
||||
SEPARATOR
|
||||
AT
|
||||
INCLUDE
|
||||
VERTLINE
|
||||
COLON
|
||||
COMMA
|
||||
NUMBER_SIGN
|
||||
SLASH
|
||||
STRING
|
||||
|
||||
rule names:
|
||||
lineStatement
|
||||
entry
|
||||
separator
|
||||
key
|
||||
values
|
||||
value
|
||||
user
|
||||
file
|
||||
command
|
||||
include
|
||||
comment
|
||||
email
|
||||
error
|
||||
errorStatus
|
||||
errorCode
|
||||
errorMessage
|
||||
|
||||
|
||||
atn:
|
||||
[4, 1, 9, 124, 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, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 1, 0, 1, 0, 3, 0, 35, 8, 0, 1, 0, 3, 0, 38, 8, 0, 1, 0, 1, 0, 1, 1, 3, 1, 43, 8, 1, 1, 1, 1, 1, 3, 1, 47, 8, 1, 1, 1, 1, 1, 3, 1, 51, 8, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 63, 8, 4, 10, 4, 12, 4, 66, 9, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 75, 8, 5, 1, 6, 1, 6, 1, 7, 1, 7, 4, 7, 81, 8, 7, 11, 7, 12, 7, 82, 1, 7, 3, 7, 86, 8, 7, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 3, 10, 98, 8, 10, 1, 10, 4, 10, 101, 8, 10, 11, 10, 12, 10, 102, 1, 10, 3, 10, 106, 8, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 0, 0, 16, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 0, 0, 122, 0, 32, 1, 0, 0, 0, 2, 42, 1, 0, 0, 0, 4, 54, 1, 0, 0, 0, 6, 56, 1, 0, 0, 0, 8, 64, 1, 0, 0, 0, 10, 74, 1, 0, 0, 0, 12, 76, 1, 0, 0, 0, 14, 80, 1, 0, 0, 0, 16, 87, 1, 0, 0, 0, 18, 90, 1, 0, 0, 0, 20, 95, 1, 0, 0, 0, 22, 107, 1, 0, 0, 0, 24, 111, 1, 0, 0, 0, 26, 117, 1, 0, 0, 0, 28, 119, 1, 0, 0, 0, 30, 121, 1, 0, 0, 0, 32, 34, 3, 2, 1, 0, 33, 35, 5, 1, 0, 0, 34, 33, 1, 0, 0, 0, 34, 35, 1, 0, 0, 0, 35, 37, 1, 0, 0, 0, 36, 38, 3, 20, 10, 0, 37, 36, 1, 0, 0, 0, 37, 38, 1, 0, 0, 0, 38, 39, 1, 0, 0, 0, 39, 40, 5, 0, 0, 1, 40, 1, 1, 0, 0, 0, 41, 43, 5, 1, 0, 0, 42, 41, 1, 0, 0, 0, 42, 43, 1, 0, 0, 0, 43, 44, 1, 0, 0, 0, 44, 46, 3, 6, 3, 0, 45, 47, 5, 1, 0, 0, 46, 45, 1, 0, 0, 0, 46, 47, 1, 0, 0, 0, 47, 48, 1, 0, 0, 0, 48, 50, 3, 4, 2, 0, 49, 51, 5, 1, 0, 0, 50, 49, 1, 0, 0, 0, 50, 51, 1, 0, 0, 0, 51, 52, 1, 0, 0, 0, 52, 53, 3, 8, 4, 0, 53, 3, 1, 0, 0, 0, 54, 55, 5, 5, 0, 0, 55, 5, 1, 0, 0, 0, 56, 57, 5, 9, 0, 0, 57, 7, 1, 0, 0, 0, 58, 59, 3, 10, 5, 0, 59, 60, 5, 6, 0, 0, 60, 61, 5, 1, 0, 0, 61, 63, 1, 0, 0, 0, 62, 58, 1, 0, 0, 0, 63, 66, 1, 0, 0, 0, 64, 62, 1, 0, 0, 0, 64, 65, 1, 0, 0, 0, 65, 67, 1, 0, 0, 0, 66, 64, 1, 0, 0, 0, 67, 68, 3, 10, 5, 0, 68, 9, 1, 0, 0, 0, 69, 75, 3, 12, 6, 0, 70, 75, 3, 14, 7, 0, 71, 75, 3, 16, 8, 0, 72, 75, 3, 18, 9, 0, 73, 75, 3, 22, 11, 0, 74, 69, 1, 0, 0, 0, 74, 70, 1, 0, 0, 0, 74, 71, 1, 0, 0, 0, 74, 72, 1, 0, 0, 0, 74, 73, 1, 0, 0, 0, 75, 11, 1, 0, 0, 0, 76, 77, 5, 9, 0, 0, 77, 13, 1, 0, 0, 0, 78, 79, 5, 8, 0, 0, 79, 81, 5, 9, 0, 0, 80, 78, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 80, 1, 0, 0, 0, 82, 83, 1, 0, 0, 0, 83, 85, 1, 0, 0, 0, 84, 86, 5, 8, 0, 0, 85, 84, 1, 0, 0, 0, 85, 86, 1, 0, 0, 0, 86, 15, 1, 0, 0, 0, 87, 88, 5, 4, 0, 0, 88, 89, 5, 9, 0, 0, 89, 17, 1, 0, 0, 0, 90, 91, 5, 5, 0, 0, 91, 92, 5, 3, 0, 0, 92, 93, 5, 5, 0, 0, 93, 94, 3, 14, 7, 0, 94, 19, 1, 0, 0, 0, 95, 100, 5, 7, 0, 0, 96, 98, 5, 1, 0, 0, 97, 96, 1, 0, 0, 0, 97, 98, 1, 0, 0, 0, 98, 99, 1, 0, 0, 0, 99, 101, 5, 9, 0, 0, 100, 97, 1, 0, 0, 0, 101, 102, 1, 0, 0, 0, 102, 100, 1, 0, 0, 0, 102, 103, 1, 0, 0, 0, 103, 105, 1, 0, 0, 0, 104, 106, 5, 1, 0, 0, 105, 104, 1, 0, 0, 0, 105, 106, 1, 0, 0, 0, 106, 21, 1, 0, 0, 0, 107, 108, 5, 9, 0, 0, 108, 109, 5, 2, 0, 0, 109, 110, 5, 9, 0, 0, 110, 23, 1, 0, 0, 0, 111, 112, 3, 26, 13, 0, 112, 113, 5, 5, 0, 0, 113, 114, 3, 28, 14, 0, 114, 115, 5, 1, 0, 0, 115, 116, 3, 30, 15, 0, 116, 25, 1, 0, 0, 0, 117, 118, 5, 9, 0, 0, 118, 27, 1, 0, 0, 0, 119, 120, 5, 9, 0, 0, 120, 29, 1, 0, 0, 0, 121, 122, 5, 9, 0, 0, 122, 31, 1, 0, 0, 0, 12, 34, 37, 42, 46, 50, 64, 74, 82, 85, 97, 102, 105]
|
15
handlers/aliases/parser/Aliases.tokens
Normal file
15
handlers/aliases/parser/Aliases.tokens
Normal file
@ -0,0 +1,15 @@
|
||||
SEPARATOR=1
|
||||
AT=2
|
||||
INCLUDE=3
|
||||
VERTLINE=4
|
||||
COLON=5
|
||||
COMMA=6
|
||||
NUMBER_SIGN=7
|
||||
SLASH=8
|
||||
STRING=9
|
||||
'@'=2
|
||||
'|'=4
|
||||
':'=5
|
||||
','=6
|
||||
'#'=7
|
||||
'/'=8
|
44
handlers/aliases/parser/AliasesLexer.interp
Normal file
44
handlers/aliases/parser/AliasesLexer.interp
Normal file
@ -0,0 +1,44 @@
|
||||
token literal names:
|
||||
null
|
||||
null
|
||||
'@'
|
||||
null
|
||||
'|'
|
||||
':'
|
||||
','
|
||||
'#'
|
||||
'/'
|
||||
null
|
||||
|
||||
token symbolic names:
|
||||
null
|
||||
SEPARATOR
|
||||
AT
|
||||
INCLUDE
|
||||
VERTLINE
|
||||
COLON
|
||||
COMMA
|
||||
NUMBER_SIGN
|
||||
SLASH
|
||||
STRING
|
||||
|
||||
rule names:
|
||||
SEPARATOR
|
||||
AT
|
||||
INCLUDE
|
||||
VERTLINE
|
||||
COLON
|
||||
COMMA
|
||||
NUMBER_SIGN
|
||||
SLASH
|
||||
STRING
|
||||
|
||||
channel names:
|
||||
DEFAULT_TOKEN_CHANNEL
|
||||
HIDDEN
|
||||
|
||||
mode names:
|
||||
DEFAULT_MODE
|
||||
|
||||
atn:
|
||||
[4, 0, 9, 49, 6, -1, 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, 2, 7, 7, 7, 2, 8, 7, 8, 1, 0, 4, 0, 21, 8, 0, 11, 0, 12, 0, 22, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 4, 8, 46, 8, 8, 11, 8, 12, 8, 47, 0, 0, 9, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 1, 0, 2, 2, 0, 9, 9, 32, 32, 9, 0, 9, 10, 13, 13, 32, 32, 35, 35, 44, 44, 47, 47, 58, 58, 64, 64, 124, 124, 50, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 1, 20, 1, 0, 0, 0, 3, 24, 1, 0, 0, 0, 5, 26, 1, 0, 0, 0, 7, 34, 1, 0, 0, 0, 9, 36, 1, 0, 0, 0, 11, 38, 1, 0, 0, 0, 13, 40, 1, 0, 0, 0, 15, 42, 1, 0, 0, 0, 17, 45, 1, 0, 0, 0, 19, 21, 7, 0, 0, 0, 20, 19, 1, 0, 0, 0, 21, 22, 1, 0, 0, 0, 22, 20, 1, 0, 0, 0, 22, 23, 1, 0, 0, 0, 23, 2, 1, 0, 0, 0, 24, 25, 5, 64, 0, 0, 25, 4, 1, 0, 0, 0, 26, 27, 5, 105, 0, 0, 27, 28, 5, 110, 0, 0, 28, 29, 5, 99, 0, 0, 29, 30, 5, 108, 0, 0, 30, 31, 5, 117, 0, 0, 31, 32, 5, 100, 0, 0, 32, 33, 5, 101, 0, 0, 33, 6, 1, 0, 0, 0, 34, 35, 5, 124, 0, 0, 35, 8, 1, 0, 0, 0, 36, 37, 5, 58, 0, 0, 37, 10, 1, 0, 0, 0, 38, 39, 5, 44, 0, 0, 39, 12, 1, 0, 0, 0, 40, 41, 5, 35, 0, 0, 41, 14, 1, 0, 0, 0, 42, 43, 5, 47, 0, 0, 43, 16, 1, 0, 0, 0, 44, 46, 8, 1, 0, 0, 45, 44, 1, 0, 0, 0, 46, 47, 1, 0, 0, 0, 47, 45, 1, 0, 0, 0, 47, 48, 1, 0, 0, 0, 48, 18, 1, 0, 0, 0, 3, 0, 22, 47, 0]
|
15
handlers/aliases/parser/AliasesLexer.tokens
Normal file
15
handlers/aliases/parser/AliasesLexer.tokens
Normal file
@ -0,0 +1,15 @@
|
||||
SEPARATOR=1
|
||||
AT=2
|
||||
INCLUDE=3
|
||||
VERTLINE=4
|
||||
COLON=5
|
||||
COMMA=6
|
||||
NUMBER_SIGN=7
|
||||
SLASH=8
|
||||
STRING=9
|
||||
'@'=2
|
||||
'|'=4
|
||||
':'=5
|
||||
','=6
|
||||
'#'=7
|
||||
'/'=8
|
118
handlers/aliases/parser/aliases_base_listener.go
Normal file
118
handlers/aliases/parser/aliases_base_listener.go
Normal file
@ -0,0 +1,118 @@
|
||||
// Code generated from Aliases.g4 by ANTLR 4.13.0. DO NOT EDIT.
|
||||
|
||||
package parser // Aliases
|
||||
|
||||
import "github.com/antlr4-go/antlr/v4"
|
||||
|
||||
// BaseAliasesListener is a complete listener for a parse tree produced by AliasesParser.
|
||||
type BaseAliasesListener struct{}
|
||||
|
||||
var _ AliasesListener = &BaseAliasesListener{}
|
||||
|
||||
// VisitTerminal is called when a terminal node is visited.
|
||||
func (s *BaseAliasesListener) VisitTerminal(node antlr.TerminalNode) {}
|
||||
|
||||
// VisitErrorNode is called when an error node is visited.
|
||||
func (s *BaseAliasesListener) VisitErrorNode(node antlr.ErrorNode) {}
|
||||
|
||||
// EnterEveryRule is called when any rule is entered.
|
||||
func (s *BaseAliasesListener) EnterEveryRule(ctx antlr.ParserRuleContext) {}
|
||||
|
||||
// ExitEveryRule is called when any rule is exited.
|
||||
func (s *BaseAliasesListener) ExitEveryRule(ctx antlr.ParserRuleContext) {}
|
||||
|
||||
// EnterLineStatement is called when production lineStatement is entered.
|
||||
func (s *BaseAliasesListener) EnterLineStatement(ctx *LineStatementContext) {}
|
||||
|
||||
// ExitLineStatement is called when production lineStatement is exited.
|
||||
func (s *BaseAliasesListener) ExitLineStatement(ctx *LineStatementContext) {}
|
||||
|
||||
// EnterEntry is called when production entry is entered.
|
||||
func (s *BaseAliasesListener) EnterEntry(ctx *EntryContext) {}
|
||||
|
||||
// ExitEntry is called when production entry is exited.
|
||||
func (s *BaseAliasesListener) ExitEntry(ctx *EntryContext) {}
|
||||
|
||||
// EnterSeparator is called when production separator is entered.
|
||||
func (s *BaseAliasesListener) EnterSeparator(ctx *SeparatorContext) {}
|
||||
|
||||
// ExitSeparator is called when production separator is exited.
|
||||
func (s *BaseAliasesListener) ExitSeparator(ctx *SeparatorContext) {}
|
||||
|
||||
// EnterKey is called when production key is entered.
|
||||
func (s *BaseAliasesListener) EnterKey(ctx *KeyContext) {}
|
||||
|
||||
// ExitKey is called when production key is exited.
|
||||
func (s *BaseAliasesListener) ExitKey(ctx *KeyContext) {}
|
||||
|
||||
// EnterValues is called when production values is entered.
|
||||
func (s *BaseAliasesListener) EnterValues(ctx *ValuesContext) {}
|
||||
|
||||
// ExitValues is called when production values is exited.
|
||||
func (s *BaseAliasesListener) ExitValues(ctx *ValuesContext) {}
|
||||
|
||||
// EnterValue is called when production value is entered.
|
||||
func (s *BaseAliasesListener) EnterValue(ctx *ValueContext) {}
|
||||
|
||||
// ExitValue is called when production value is exited.
|
||||
func (s *BaseAliasesListener) ExitValue(ctx *ValueContext) {}
|
||||
|
||||
// EnterUser is called when production user is entered.
|
||||
func (s *BaseAliasesListener) EnterUser(ctx *UserContext) {}
|
||||
|
||||
// ExitUser is called when production user is exited.
|
||||
func (s *BaseAliasesListener) ExitUser(ctx *UserContext) {}
|
||||
|
||||
// EnterFile is called when production file is entered.
|
||||
func (s *BaseAliasesListener) EnterFile(ctx *FileContext) {}
|
||||
|
||||
// ExitFile is called when production file is exited.
|
||||
func (s *BaseAliasesListener) ExitFile(ctx *FileContext) {}
|
||||
|
||||
// EnterCommand is called when production command is entered.
|
||||
func (s *BaseAliasesListener) EnterCommand(ctx *CommandContext) {}
|
||||
|
||||
// ExitCommand is called when production command is exited.
|
||||
func (s *BaseAliasesListener) ExitCommand(ctx *CommandContext) {}
|
||||
|
||||
// EnterInclude is called when production include is entered.
|
||||
func (s *BaseAliasesListener) EnterInclude(ctx *IncludeContext) {}
|
||||
|
||||
// ExitInclude is called when production include is exited.
|
||||
func (s *BaseAliasesListener) ExitInclude(ctx *IncludeContext) {}
|
||||
|
||||
// EnterComment is called when production comment is entered.
|
||||
func (s *BaseAliasesListener) EnterComment(ctx *CommentContext) {}
|
||||
|
||||
// ExitComment is called when production comment is exited.
|
||||
func (s *BaseAliasesListener) ExitComment(ctx *CommentContext) {}
|
||||
|
||||
// EnterEmail is called when production email is entered.
|
||||
func (s *BaseAliasesListener) EnterEmail(ctx *EmailContext) {}
|
||||
|
||||
// ExitEmail is called when production email is exited.
|
||||
func (s *BaseAliasesListener) ExitEmail(ctx *EmailContext) {}
|
||||
|
||||
// EnterError is called when production error is entered.
|
||||
func (s *BaseAliasesListener) EnterError(ctx *ErrorContext) {}
|
||||
|
||||
// ExitError is called when production error is exited.
|
||||
func (s *BaseAliasesListener) ExitError(ctx *ErrorContext) {}
|
||||
|
||||
// EnterErrorStatus is called when production errorStatus is entered.
|
||||
func (s *BaseAliasesListener) EnterErrorStatus(ctx *ErrorStatusContext) {}
|
||||
|
||||
// ExitErrorStatus is called when production errorStatus is exited.
|
||||
func (s *BaseAliasesListener) ExitErrorStatus(ctx *ErrorStatusContext) {}
|
||||
|
||||
// EnterErrorCode is called when production errorCode is entered.
|
||||
func (s *BaseAliasesListener) EnterErrorCode(ctx *ErrorCodeContext) {}
|
||||
|
||||
// ExitErrorCode is called when production errorCode is exited.
|
||||
func (s *BaseAliasesListener) ExitErrorCode(ctx *ErrorCodeContext) {}
|
||||
|
||||
// EnterErrorMessage is called when production errorMessage is entered.
|
||||
func (s *BaseAliasesListener) EnterErrorMessage(ctx *ErrorMessageContext) {}
|
||||
|
||||
// ExitErrorMessage is called when production errorMessage is exited.
|
||||
func (s *BaseAliasesListener) ExitErrorMessage(ctx *ErrorMessageContext) {}
|
129
handlers/aliases/parser/aliases_lexer.go
Normal file
129
handlers/aliases/parser/aliases_lexer.go
Normal file
@ -0,0 +1,129 @@
|
||||
// Code generated from Aliases.g4 by ANTLR 4.13.0. DO NOT EDIT.
|
||||
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/antlr4-go/antlr/v4"
|
||||
"sync"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// Suppress unused import error
|
||||
var _ = fmt.Printf
|
||||
var _ = sync.Once{}
|
||||
var _ = unicode.IsLetter
|
||||
|
||||
type AliasesLexer struct {
|
||||
*antlr.BaseLexer
|
||||
channelNames []string
|
||||
modeNames []string
|
||||
// TODO: EOF string
|
||||
}
|
||||
|
||||
var AliasesLexerLexerStaticData struct {
|
||||
once sync.Once
|
||||
serializedATN []int32
|
||||
ChannelNames []string
|
||||
ModeNames []string
|
||||
LiteralNames []string
|
||||
SymbolicNames []string
|
||||
RuleNames []string
|
||||
PredictionContextCache *antlr.PredictionContextCache
|
||||
atn *antlr.ATN
|
||||
decisionToDFA []*antlr.DFA
|
||||
}
|
||||
|
||||
func aliaseslexerLexerInit() {
|
||||
staticData := &AliasesLexerLexerStaticData
|
||||
staticData.ChannelNames = []string{
|
||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN",
|
||||
}
|
||||
staticData.ModeNames = []string{
|
||||
"DEFAULT_MODE",
|
||||
}
|
||||
staticData.LiteralNames = []string{
|
||||
"", "", "'@'", "", "'|'", "':'", "','", "'#'", "'/'",
|
||||
}
|
||||
staticData.SymbolicNames = []string{
|
||||
"", "SEPARATOR", "AT", "INCLUDE", "VERTLINE", "COLON", "COMMA", "NUMBER_SIGN",
|
||||
"SLASH", "STRING",
|
||||
}
|
||||
staticData.RuleNames = []string{
|
||||
"SEPARATOR", "AT", "INCLUDE", "VERTLINE", "COLON", "COMMA", "NUMBER_SIGN",
|
||||
"SLASH", "STRING",
|
||||
}
|
||||
staticData.PredictionContextCache = antlr.NewPredictionContextCache()
|
||||
staticData.serializedATN = []int32{
|
||||
4, 0, 9, 49, 6, -1, 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, 2, 7, 7, 7, 2, 8, 7, 8, 1, 0, 4, 0, 21,
|
||||
8, 0, 11, 0, 12, 0, 22, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
|
||||
1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7,
|
||||
1, 8, 4, 8, 46, 8, 8, 11, 8, 12, 8, 47, 0, 0, 9, 1, 1, 3, 2, 5, 3, 7, 4,
|
||||
9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 1, 0, 2, 2, 0, 9, 9, 32, 32, 9, 0, 9,
|
||||
10, 13, 13, 32, 32, 35, 35, 44, 44, 47, 47, 58, 58, 64, 64, 124, 124, 50,
|
||||
0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0,
|
||||
0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0,
|
||||
0, 0, 17, 1, 0, 0, 0, 1, 20, 1, 0, 0, 0, 3, 24, 1, 0, 0, 0, 5, 26, 1, 0,
|
||||
0, 0, 7, 34, 1, 0, 0, 0, 9, 36, 1, 0, 0, 0, 11, 38, 1, 0, 0, 0, 13, 40,
|
||||
1, 0, 0, 0, 15, 42, 1, 0, 0, 0, 17, 45, 1, 0, 0, 0, 19, 21, 7, 0, 0, 0,
|
||||
20, 19, 1, 0, 0, 0, 21, 22, 1, 0, 0, 0, 22, 20, 1, 0, 0, 0, 22, 23, 1,
|
||||
0, 0, 0, 23, 2, 1, 0, 0, 0, 24, 25, 5, 64, 0, 0, 25, 4, 1, 0, 0, 0, 26,
|
||||
27, 5, 105, 0, 0, 27, 28, 5, 110, 0, 0, 28, 29, 5, 99, 0, 0, 29, 30, 5,
|
||||
108, 0, 0, 30, 31, 5, 117, 0, 0, 31, 32, 5, 100, 0, 0, 32, 33, 5, 101,
|
||||
0, 0, 33, 6, 1, 0, 0, 0, 34, 35, 5, 124, 0, 0, 35, 8, 1, 0, 0, 0, 36, 37,
|
||||
5, 58, 0, 0, 37, 10, 1, 0, 0, 0, 38, 39, 5, 44, 0, 0, 39, 12, 1, 0, 0,
|
||||
0, 40, 41, 5, 35, 0, 0, 41, 14, 1, 0, 0, 0, 42, 43, 5, 47, 0, 0, 43, 16,
|
||||
1, 0, 0, 0, 44, 46, 8, 1, 0, 0, 45, 44, 1, 0, 0, 0, 46, 47, 1, 0, 0, 0,
|
||||
47, 45, 1, 0, 0, 0, 47, 48, 1, 0, 0, 0, 48, 18, 1, 0, 0, 0, 3, 0, 22, 47,
|
||||
0,
|
||||
}
|
||||
deserializer := antlr.NewATNDeserializer(nil)
|
||||
staticData.atn = deserializer.Deserialize(staticData.serializedATN)
|
||||
atn := staticData.atn
|
||||
staticData.decisionToDFA = make([]*antlr.DFA, len(atn.DecisionToState))
|
||||
decisionToDFA := staticData.decisionToDFA
|
||||
for index, state := range atn.DecisionToState {
|
||||
decisionToDFA[index] = antlr.NewDFA(state, index)
|
||||
}
|
||||
}
|
||||
|
||||
// AliasesLexerInit initializes any static state used to implement AliasesLexer. By default the
|
||||
// static state used to implement the lexer is lazily initialized during the first call to
|
||||
// NewAliasesLexer(). You can call this function if you wish to initialize the static state ahead
|
||||
// of time.
|
||||
func AliasesLexerInit() {
|
||||
staticData := &AliasesLexerLexerStaticData
|
||||
staticData.once.Do(aliaseslexerLexerInit)
|
||||
}
|
||||
|
||||
// NewAliasesLexer produces a new lexer instance for the optional input antlr.CharStream.
|
||||
func NewAliasesLexer(input antlr.CharStream) *AliasesLexer {
|
||||
AliasesLexerInit()
|
||||
l := new(AliasesLexer)
|
||||
l.BaseLexer = antlr.NewBaseLexer(input)
|
||||
staticData := &AliasesLexerLexerStaticData
|
||||
l.Interpreter = antlr.NewLexerATNSimulator(l, staticData.atn, staticData.decisionToDFA, staticData.PredictionContextCache)
|
||||
l.channelNames = staticData.ChannelNames
|
||||
l.modeNames = staticData.ModeNames
|
||||
l.RuleNames = staticData.RuleNames
|
||||
l.LiteralNames = staticData.LiteralNames
|
||||
l.SymbolicNames = staticData.SymbolicNames
|
||||
l.GrammarFileName = "Aliases.g4"
|
||||
// TODO: l.EOF = antlr.TokenEOF
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
// AliasesLexer tokens.
|
||||
const (
|
||||
AliasesLexerSEPARATOR = 1
|
||||
AliasesLexerAT = 2
|
||||
AliasesLexerINCLUDE = 3
|
||||
AliasesLexerVERTLINE = 4
|
||||
AliasesLexerCOLON = 5
|
||||
AliasesLexerCOMMA = 6
|
||||
AliasesLexerNUMBER_SIGN = 7
|
||||
AliasesLexerSLASH = 8
|
||||
AliasesLexerSTRING = 9
|
||||
)
|
106
handlers/aliases/parser/aliases_listener.go
Normal file
106
handlers/aliases/parser/aliases_listener.go
Normal file
@ -0,0 +1,106 @@
|
||||
// Code generated from Aliases.g4 by ANTLR 4.13.0. DO NOT EDIT.
|
||||
|
||||
package parser // Aliases
|
||||
|
||||
import "github.com/antlr4-go/antlr/v4"
|
||||
|
||||
// AliasesListener is a complete listener for a parse tree produced by AliasesParser.
|
||||
type AliasesListener interface {
|
||||
antlr.ParseTreeListener
|
||||
|
||||
// EnterLineStatement is called when entering the lineStatement production.
|
||||
EnterLineStatement(c *LineStatementContext)
|
||||
|
||||
// EnterEntry is called when entering the entry production.
|
||||
EnterEntry(c *EntryContext)
|
||||
|
||||
// EnterSeparator is called when entering the separator production.
|
||||
EnterSeparator(c *SeparatorContext)
|
||||
|
||||
// EnterKey is called when entering the key production.
|
||||
EnterKey(c *KeyContext)
|
||||
|
||||
// EnterValues is called when entering the values production.
|
||||
EnterValues(c *ValuesContext)
|
||||
|
||||
// EnterValue is called when entering the value production.
|
||||
EnterValue(c *ValueContext)
|
||||
|
||||
// EnterUser is called when entering the user production.
|
||||
EnterUser(c *UserContext)
|
||||
|
||||
// EnterFile is called when entering the file production.
|
||||
EnterFile(c *FileContext)
|
||||
|
||||
// EnterCommand is called when entering the command production.
|
||||
EnterCommand(c *CommandContext)
|
||||
|
||||
// EnterInclude is called when entering the include production.
|
||||
EnterInclude(c *IncludeContext)
|
||||
|
||||
// EnterComment is called when entering the comment production.
|
||||
EnterComment(c *CommentContext)
|
||||
|
||||
// EnterEmail is called when entering the email production.
|
||||
EnterEmail(c *EmailContext)
|
||||
|
||||
// EnterError is called when entering the error production.
|
||||
EnterError(c *ErrorContext)
|
||||
|
||||
// EnterErrorStatus is called when entering the errorStatus production.
|
||||
EnterErrorStatus(c *ErrorStatusContext)
|
||||
|
||||
// EnterErrorCode is called when entering the errorCode production.
|
||||
EnterErrorCode(c *ErrorCodeContext)
|
||||
|
||||
// EnterErrorMessage is called when entering the errorMessage production.
|
||||
EnterErrorMessage(c *ErrorMessageContext)
|
||||
|
||||
// ExitLineStatement is called when exiting the lineStatement production.
|
||||
ExitLineStatement(c *LineStatementContext)
|
||||
|
||||
// ExitEntry is called when exiting the entry production.
|
||||
ExitEntry(c *EntryContext)
|
||||
|
||||
// ExitSeparator is called when exiting the separator production.
|
||||
ExitSeparator(c *SeparatorContext)
|
||||
|
||||
// ExitKey is called when exiting the key production.
|
||||
ExitKey(c *KeyContext)
|
||||
|
||||
// ExitValues is called when exiting the values production.
|
||||
ExitValues(c *ValuesContext)
|
||||
|
||||
// ExitValue is called when exiting the value production.
|
||||
ExitValue(c *ValueContext)
|
||||
|
||||
// ExitUser is called when exiting the user production.
|
||||
ExitUser(c *UserContext)
|
||||
|
||||
// ExitFile is called when exiting the file production.
|
||||
ExitFile(c *FileContext)
|
||||
|
||||
// ExitCommand is called when exiting the command production.
|
||||
ExitCommand(c *CommandContext)
|
||||
|
||||
// ExitInclude is called when exiting the include production.
|
||||
ExitInclude(c *IncludeContext)
|
||||
|
||||
// ExitComment is called when exiting the comment production.
|
||||
ExitComment(c *CommentContext)
|
||||
|
||||
// ExitEmail is called when exiting the email production.
|
||||
ExitEmail(c *EmailContext)
|
||||
|
||||
// ExitError is called when exiting the error production.
|
||||
ExitError(c *ErrorContext)
|
||||
|
||||
// ExitErrorStatus is called when exiting the errorStatus production.
|
||||
ExitErrorStatus(c *ErrorStatusContext)
|
||||
|
||||
// ExitErrorCode is called when exiting the errorCode production.
|
||||
ExitErrorCode(c *ErrorCodeContext)
|
||||
|
||||
// ExitErrorMessage is called when exiting the errorMessage production.
|
||||
ExitErrorMessage(c *ErrorMessageContext)
|
||||
}
|
2424
handlers/aliases/parser/aliases_parser.go
Normal file
2424
handlers/aliases/parser/aliases_parser.go
Normal file
File diff suppressed because it is too large
Load Diff
39
handlers/aliases/tree/aliases.go
Normal file
39
handlers/aliases/tree/aliases.go
Normal file
@ -0,0 +1,39 @@
|
||||
package tree
|
||||
|
||||
import (
|
||||
"config-lsp/common"
|
||||
)
|
||||
|
||||
// Procedure
|
||||
// Save options in fields
|
||||
// Each type, such as Include, User etc is own type
|
||||
// Each type inherits interface
|
||||
// This interface has methods such as:
|
||||
// - CheckIsUser()
|
||||
// For user, this checks if the user is listed in passwd
|
||||
// For include, this includes the file and parses it and validates it
|
||||
//
|
||||
|
||||
// Parse content manually as the /etc/aliases file is so simple
|
||||
|
||||
type AliasKey struct {
|
||||
Location common.LocationRange
|
||||
Value string
|
||||
}
|
||||
|
||||
type AliasValues struct {
|
||||
Location common.LocationRange
|
||||
Values []AliasValueInterface
|
||||
}
|
||||
|
||||
type AliasEntry struct {
|
||||
Location common.LocationRange
|
||||
Key *AliasKey
|
||||
Separator *common.LocationRange
|
||||
Values *AliasValues
|
||||
}
|
||||
|
||||
type AliasesParser struct {
|
||||
Aliases map[uint32]*AliasEntry
|
||||
CommentLines map[uint32]struct{}
|
||||
}
|
1
handlers/aliases/tree/handler.go
Normal file
1
handlers/aliases/tree/handler.go
Normal file
@ -0,0 +1 @@
|
||||
package tree
|
208
handlers/aliases/tree/listener.go
Normal file
208
handlers/aliases/tree/listener.go
Normal file
@ -0,0 +1,208 @@
|
||||
package tree
|
||||
|
||||
import (
|
||||
"config-lsp/common"
|
||||
"config-lsp/handlers/aliases/parser"
|
||||
|
||||
"github.com/antlr4-go/antlr/v4"
|
||||
)
|
||||
|
||||
type aliasesListenerContext struct {
|
||||
line uint32
|
||||
currentIncludeIndex *uint32
|
||||
}
|
||||
|
||||
type aliasesParserListener struct {
|
||||
*parser.BaseAliasesListener
|
||||
Parser *AliasesParser
|
||||
Errors []common.LSPError
|
||||
aliasContext aliasesListenerContext
|
||||
}
|
||||
|
||||
func (s *aliasesParserListener) EnterEntry(ctx *parser.EntryContext) {
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.aliasContext.line)
|
||||
|
||||
s.Parser.Aliases[location.Start.Line] = &AliasEntry{
|
||||
Location: location,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *aliasesParserListener) EnterSeparator(ctx *parser.SeparatorContext) {
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.aliasContext.line)
|
||||
|
||||
entry := s.Parser.Aliases[location.Start.Line]
|
||||
entry.Separator = &location
|
||||
}
|
||||
|
||||
func (s *aliasesParserListener) EnterKey(ctx *parser.KeyContext) {
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.aliasContext.line)
|
||||
|
||||
entry := s.Parser.Aliases[location.Start.Line]
|
||||
entry.Key = &AliasKey{
|
||||
Location: location,
|
||||
Value: ctx.GetText(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *aliasesParserListener) EnterValues(ctx *parser.ValuesContext) {
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.aliasContext.line)
|
||||
|
||||
entry := s.Parser.Aliases[location.Start.Line]
|
||||
entry.Values = &AliasValues{
|
||||
Location: location,
|
||||
Values: make([]AliasValueInterface, 0, 5),
|
||||
}
|
||||
}
|
||||
|
||||
// === Value === //
|
||||
|
||||
func (s *aliasesParserListener) EnterUser(ctx *parser.UserContext) {
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.aliasContext.line)
|
||||
|
||||
user := AliasValueUser{
|
||||
AliasValue: AliasValue{
|
||||
Location: location,
|
||||
Value: ctx.GetText(),
|
||||
},
|
||||
}
|
||||
|
||||
entry := s.Parser.Aliases[location.Start.Line]
|
||||
entry.Values.Values = append(entry.Values.Values, user)
|
||||
}
|
||||
|
||||
func (s *aliasesParserListener) EnterFile(ctx *parser.FileContext) {
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.aliasContext.line)
|
||||
|
||||
if s.aliasContext.currentIncludeIndex != nil {
|
||||
// This `file` is inside an `include`, so we need to set the path on the include
|
||||
values := s.Parser.Aliases[location.Start.Line].Values
|
||||
rawValue := values.Values[*s.aliasContext.currentIncludeIndex]
|
||||
|
||||
// Set the path
|
||||
include := rawValue.(AliasValueInclude)
|
||||
include.Path = AliasValueIncludePath{
|
||||
Location: location,
|
||||
Path: path(ctx.GetText()),
|
||||
}
|
||||
values.Values[*s.aliasContext.currentIncludeIndex] = include
|
||||
|
||||
// Clean up
|
||||
s.aliasContext.currentIncludeIndex = nil
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Raw file, process it
|
||||
file := AliasValueFile{
|
||||
AliasValue: AliasValue{
|
||||
Location: location,
|
||||
Value: ctx.GetText(),
|
||||
},
|
||||
Path: path(ctx.GetText()),
|
||||
}
|
||||
|
||||
entry := s.Parser.Aliases[location.Start.Line]
|
||||
entry.Values.Values = append(entry.Values.Values, file)
|
||||
}
|
||||
|
||||
func (s *aliasesParserListener) EnterCommand(ctx *parser.CommandContext) {
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.aliasContext.line)
|
||||
|
||||
command := AliasValueCommand{
|
||||
AliasValue: AliasValue{
|
||||
Location: location,
|
||||
Value: ctx.GetText(),
|
||||
},
|
||||
Command: ctx.GetText()[1:],
|
||||
}
|
||||
|
||||
entry := s.Parser.Aliases[location.Start.Line]
|
||||
entry.Values.Values = append(entry.Values.Values, command)
|
||||
}
|
||||
|
||||
func (s *aliasesParserListener) EnterInclude(ctx *parser.IncludeContext) {
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.aliasContext.line)
|
||||
|
||||
include := AliasValueInclude{
|
||||
AliasValue: AliasValue{
|
||||
Location: location,
|
||||
Value: ctx.GetText(),
|
||||
},
|
||||
}
|
||||
|
||||
entry := s.Parser.Aliases[location.Start.Line]
|
||||
entry.Values.Values = append(entry.Values.Values, include)
|
||||
|
||||
index := uint32(len(entry.Values.Values) - 1)
|
||||
s.aliasContext.currentIncludeIndex = &index
|
||||
}
|
||||
|
||||
func (s *aliasesParserListener) EnterEmail(ctx *parser.EmailContext) {
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.aliasContext.line)
|
||||
|
||||
email := AliasValueEmail{
|
||||
AliasValue: AliasValue{
|
||||
Location: location,
|
||||
Value: ctx.GetText(),
|
||||
},
|
||||
}
|
||||
|
||||
entry := s.Parser.Aliases[location.Start.Line]
|
||||
entry.Values.Values = append(entry.Values.Values, email)
|
||||
}
|
||||
|
||||
func createListener(
|
||||
parser *AliasesParser,
|
||||
line uint32,
|
||||
) aliasesParserListener {
|
||||
return aliasesParserListener{
|
||||
Parser: parser,
|
||||
aliasContext: aliasesListenerContext{
|
||||
line: line,
|
||||
},
|
||||
Errors: make([]common.LSPError, 0),
|
||||
}
|
||||
}
|
||||
|
||||
type errorListener struct {
|
||||
*antlr.DefaultErrorListener
|
||||
Errors []common.LSPError
|
||||
context aliasesListenerContext
|
||||
}
|
||||
|
||||
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: aliasesListenerContext{
|
||||
line: line,
|
||||
},
|
||||
}
|
||||
}
|
79
handlers/aliases/tree/parser.go
Normal file
79
handlers/aliases/tree/parser.go
Normal file
@ -0,0 +1,79 @@
|
||||
package tree
|
||||
|
||||
import (
|
||||
"config-lsp/common"
|
||||
"config-lsp/handlers/aliases/parser"
|
||||
"config-lsp/utils"
|
||||
"github.com/antlr4-go/antlr/v4"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func NewAliasesParser() AliasesParser {
|
||||
p := AliasesParser{}
|
||||
p.Clear()
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *AliasesParser) Clear() {
|
||||
p.CommentLines = make(map[uint32]struct{})
|
||||
p.Aliases = make(map[uint32]*AliasEntry)
|
||||
}
|
||||
|
||||
var commentPattern = regexp.MustCompile(`^\s*#.*$`)
|
||||
var emptyPattern = regexp.MustCompile(`^\s*$`)
|
||||
|
||||
func (p *AliasesParser) Parse(input string) []common.LSPError {
|
||||
errors := make([]common.LSPError, 0)
|
||||
lines := utils.SplitIntoLines(input)
|
||||
|
||||
for rawLineNumber, line := range lines {
|
||||
lineNumber := uint32(rawLineNumber)
|
||||
|
||||
if commentPattern.MatchString(line) {
|
||||
p.CommentLines[lineNumber] = struct{}{}
|
||||
continue
|
||||
}
|
||||
|
||||
if emptyPattern.MatchString(line) {
|
||||
continue
|
||||
}
|
||||
|
||||
errors = append(
|
||||
errors,
|
||||
p.parseStatement(lineNumber, line)...,
|
||||
)
|
||||
}
|
||||
|
||||
return errors
|
||||
}
|
||||
|
||||
func (p *AliasesParser) parseStatement(
|
||||
line uint32,
|
||||
input string,
|
||||
) []common.LSPError {
|
||||
stream := antlr.NewInputStream(input)
|
||||
|
||||
lexerErrorListener := createErrorListener(line)
|
||||
lexer := parser.NewAliasesLexer(stream)
|
||||
lexer.RemoveErrorListeners()
|
||||
lexer.AddErrorListener(&lexerErrorListener)
|
||||
|
||||
tokenStream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
|
||||
|
||||
parserErrorListener := createErrorListener(line)
|
||||
antlrParser := parser.NewAliasesParser(tokenStream)
|
||||
antlrParser.RemoveErrorListeners()
|
||||
antlrParser.AddErrorListener(&parserErrorListener)
|
||||
|
||||
listener := createListener(p, line)
|
||||
antlr.ParseTreeWalkerDefault.Walk(
|
||||
&listener,
|
||||
antlrParser.LineStatement(),
|
||||
)
|
||||
|
||||
errors := lexerErrorListener.Errors
|
||||
errors = append(errors, parserErrorListener.Errors...)
|
||||
|
||||
return errors
|
||||
}
|
107
handlers/aliases/tree/parser_test.go
Normal file
107
handlers/aliases/tree/parser_test.go
Normal file
@ -0,0 +1,107 @@
|
||||
package tree
|
||||
|
||||
import (
|
||||
"config-lsp/utils"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSimpleExampleWorks(
|
||||
t *testing.T,
|
||||
) {
|
||||
input := utils.Dedent(`
|
||||
postmaster: root
|
||||
`)
|
||||
|
||||
parser := NewAliasesParser()
|
||||
errors := parser.Parse(input)
|
||||
|
||||
if len(errors) != 0 {
|
||||
t.Fatalf("Expected no errors, got %v", errors)
|
||||
}
|
||||
|
||||
if !(len(parser.Aliases) == 1) {
|
||||
t.Fatalf("Expected 1 alias, got %v", len(parser.Aliases))
|
||||
}
|
||||
|
||||
if !(parser.Aliases[0].Key.Value == "postmaster") {
|
||||
t.Fatalf("Expected key to be 'postmaster', got %v", parser.Aliases[1].Key.Value)
|
||||
}
|
||||
|
||||
userValue := parser.Aliases[0].Values.Values[0].(AliasValueUser)
|
||||
if !(userValue.Value == "root") {
|
||||
t.Fatalf("Expected value to be 'root', got %v", userValue.Value)
|
||||
}
|
||||
|
||||
if !(userValue.Location.Start.Line == 0) {
|
||||
t.Fatalf("Expected start line to be 0, got %v", userValue.Location.Start.Line)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultipleValuesWorks(
|
||||
t *testing.T,
|
||||
) {
|
||||
input := utils.Dedent(`
|
||||
heinz: root, goli
|
||||
michel: raiks@example.com
|
||||
`)
|
||||
parser := NewAliasesParser()
|
||||
errors := parser.Parse(input)
|
||||
|
||||
if len(errors) != 0 {
|
||||
t.Fatalf("Expected no errors, got %v", errors)
|
||||
}
|
||||
|
||||
if !(len(parser.Aliases) == 2) {
|
||||
t.Fatalf("Expected 2 aliases, got %v", len(parser.Aliases))
|
||||
}
|
||||
|
||||
if !(parser.Aliases[0].Key.Value == "heinz") {
|
||||
t.Fatalf("Expected key to be 'heinz', got %v", parser.Aliases[1].Key.Value)
|
||||
}
|
||||
|
||||
if !(parser.Aliases[1].Key.Value == "michel") {
|
||||
t.Fatalf("Expected key to be 'michel', got %v", parser.Aliases[1].Key.Value)
|
||||
}
|
||||
|
||||
emailValue := parser.Aliases[1].Values.Values[0].(AliasValueEmail)
|
||||
|
||||
if !(emailValue.Value == "raiks@example.com") {
|
||||
t.Fatalf("Expected value to be 'raiks@example.com', got %v", emailValue.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIncludeWorks(
|
||||
t *testing.T,
|
||||
) {
|
||||
input := utils.Dedent(`
|
||||
luke: :include:/etc/other_aliases
|
||||
`)
|
||||
parser := NewAliasesParser()
|
||||
errors := parser.Parse(input)
|
||||
|
||||
if len(errors) != 0 {
|
||||
t.Fatalf("Expected no errors, got %v", errors)
|
||||
}
|
||||
|
||||
if !(len(parser.Aliases) == 1) {
|
||||
t.Fatalf("Expected 1 alias, got %v", len(parser.Aliases))
|
||||
}
|
||||
|
||||
if !(parser.Aliases[0].Key.Value == "luke") {
|
||||
t.Fatalf("Expected key to be 'luke', got %v", parser.Aliases[1].Key.Value)
|
||||
}
|
||||
|
||||
includeValue := parser.Aliases[0].Values.Values[0].(AliasValueInclude)
|
||||
|
||||
if !(includeValue.Path.Path == "/etc/other_aliases") {
|
||||
t.Fatalf("Expected path to be '/etc/other_aliases', got %v", includeValue.Path.Path)
|
||||
}
|
||||
|
||||
if !(includeValue.Location.Start.Character == 6 && includeValue.Location.End.Character == 33) {
|
||||
t.Fatalf("Expected location to be 6-33, got %v-%v", includeValue.Location.Start.Character, includeValue.Location.End.Character)
|
||||
}
|
||||
|
||||
if !(includeValue.Path.Location.Start.Character == 15 && includeValue.Path.Location.End.Character == 33) {
|
||||
t.Fatalf("Expected path location to be 15-33, got %v-%v", includeValue.Path.Location.Start.Character, includeValue.Path.Location.End.Character)
|
||||
}
|
||||
}
|
55
handlers/aliases/tree/values.go
Normal file
55
handlers/aliases/tree/values.go
Normal file
@ -0,0 +1,55 @@
|
||||
package tree
|
||||
|
||||
import (
|
||||
"config-lsp/common"
|
||||
docvalues "config-lsp/doc-values"
|
||||
|
||||
protocol "github.com/tliron/glsp/protocol_3_16"
|
||||
)
|
||||
|
||||
type AliasValueInterface interface {
|
||||
FetchCompletions(line string, cursor uint32) []protocol.CompletionItem
|
||||
CheckIsValid() []*docvalues.InvalidValue
|
||||
}
|
||||
|
||||
func (a AliasValue) FetchCompletions(line string, cursor uint32) []protocol.CompletionItem {
|
||||
return nil
|
||||
}
|
||||
func (a AliasValue) CheckIsValid() []*docvalues.InvalidValue {
|
||||
return nil
|
||||
}
|
||||
|
||||
type AliasValue struct {
|
||||
Location common.LocationRange
|
||||
Value string
|
||||
}
|
||||
|
||||
type AliasValueUser struct {
|
||||
AliasValue
|
||||
}
|
||||
|
||||
type path string
|
||||
|
||||
type AliasValueFile struct {
|
||||
AliasValue
|
||||
Path path
|
||||
}
|
||||
|
||||
type AliasValueCommand struct {
|
||||
AliasValue
|
||||
Command string
|
||||
}
|
||||
|
||||
type AliasValueIncludePath struct {
|
||||
Location common.LocationRange
|
||||
Path path
|
||||
}
|
||||
|
||||
type AliasValueInclude struct {
|
||||
AliasValue
|
||||
Path AliasValueIncludePath
|
||||
}
|
||||
|
||||
type AliasValueEmail struct {
|
||||
AliasValue
|
||||
}
|
@ -4,29 +4,8 @@ import (
|
||||
"config-lsp/common"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/antlr4-go/antlr/v4"
|
||||
)
|
||||
|
||||
func characterRangeFromCtx(
|
||||
ctx antlr.BaseParserRuleContext,
|
||||
) common.LocationRange {
|
||||
line := uint32(ctx.GetStart().GetLine())
|
||||
start := uint32(ctx.GetStart().GetStart())
|
||||
end := uint32(ctx.GetStop().GetStop())
|
||||
|
||||
return common.LocationRange{
|
||||
Start: common.Location{
|
||||
Line: line,
|
||||
Character: start,
|
||||
},
|
||||
End: common.Location{
|
||||
Line: line,
|
||||
Character: end + 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type HostsParser struct {
|
||||
Tree HostsTree
|
||||
CommentLines map[uint32]struct{}
|
||||
|
@ -26,7 +26,7 @@ func (s *hostsParserListener) EnterComment(ctx *parser.CommentContext) {
|
||||
}
|
||||
|
||||
func (s *hostsParserListener) EnterEntry(ctx *parser.EntryContext) {
|
||||
location := characterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.hostsContext.line)
|
||||
|
||||
s.Parser.Tree.Entries[location.Start.Line] = &HostsEntry{
|
||||
@ -35,7 +35,7 @@ func (s *hostsParserListener) EnterEntry(ctx *parser.EntryContext) {
|
||||
}
|
||||
|
||||
func (s *hostsParserListener) EnterIpAddress(ctx *parser.IpAddressContext) {
|
||||
location := characterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.hostsContext.line)
|
||||
|
||||
ip := net.ParseIP(ctx.GetText())
|
||||
@ -66,7 +66,7 @@ func (s *hostsParserListener) EnterIpAddress(ctx *parser.IpAddressContext) {
|
||||
}
|
||||
|
||||
func (s *hostsParserListener) EnterHostname(ctx *parser.HostnameContext) {
|
||||
location := characterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.hostsContext.line)
|
||||
|
||||
entry := s.Parser.Tree.Entries[location.Start.Line]
|
||||
@ -80,7 +80,7 @@ func (s *hostsParserListener) EnterHostname(ctx *parser.HostnameContext) {
|
||||
}
|
||||
|
||||
func (s *hostsParserListener) EnterAliases(ctx *parser.AliasesContext) {
|
||||
location := characterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.hostsContext.line)
|
||||
|
||||
entry := s.Parser.Tree.Entries[location.Start.Line]
|
||||
@ -91,7 +91,7 @@ func (s *hostsParserListener) EnterAliases(ctx *parser.AliasesContext) {
|
||||
}
|
||||
|
||||
func (s *hostsParserListener) EnterAlias(ctx *parser.AliasContext) {
|
||||
location := characterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location := common.CharacterRangeFromCtx(ctx.BaseParserRuleContext)
|
||||
location.ChangeBothLines(s.hostsContext.line)
|
||||
|
||||
entry := s.Parser.Tree.Entries[location.Start.Line]
|
||||
@ -123,17 +123,6 @@ type errorListener struct {
|
||||
hostsContext hostsListenerContext
|
||||
}
|
||||
|
||||
func createErrorListener(
|
||||
line uint32,
|
||||
) errorListener {
|
||||
return errorListener{
|
||||
Errors: make([]common.LSPError, 0),
|
||||
hostsContext: hostsListenerContext{
|
||||
line: line,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *errorListener) SyntaxError(
|
||||
recognizer antlr.Recognizer,
|
||||
offendingSymbol interface{},
|
||||
@ -150,3 +139,14 @@ func (d *errorListener) SyntaxError(
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func createErrorListener(
|
||||
line uint32,
|
||||
) errorListener {
|
||||
return errorListener{
|
||||
Errors: make([]common.LSPError, 0),
|
||||
hostsContext: hostsListenerContext{
|
||||
line: line,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user