feature: refactor api parse to g4 (#365)
* feature: refactor api parse to g4 * new g4 parser * add CHANGE_LOG.MD * refactor * fix byte bug * refactor * optimized * optimized * revert * update readme.md * update readme.md * update readme.md * update readme.md * remove no need * fix java gen * add upgrade * resolve confilits Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
This commit is contained in:
156
tools/goctl/api/parser/g4/gen/api/apiparser_base_visitor.go
Normal file
156
tools/goctl/api/parser/g4/gen/api/apiparser_base_visitor.go
Normal file
@@ -0,0 +1,156 @@
|
||||
// Code generated from tools/goctl/api/parser/g4/ApiParser.g4 by ANTLR 4.9. DO NOT EDIT.
|
||||
|
||||
package api // ApiParser
|
||||
import "github.com/antlr/antlr4/runtime/Go/antlr"
|
||||
|
||||
type BaseApiParserVisitor struct {
|
||||
*antlr.BaseParseTreeVisitor
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitApi(ctx *ApiContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitSpec(ctx *SpecContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitSyntaxLit(ctx *SyntaxLitContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitImportSpec(ctx *ImportSpecContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitImportLit(ctx *ImportLitContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitImportBlock(ctx *ImportBlockContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitImportBlockValue(ctx *ImportBlockValueContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitImportValue(ctx *ImportValueContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitInfoSpec(ctx *InfoSpecContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitTypeSpec(ctx *TypeSpecContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitTypeLit(ctx *TypeLitContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitTypeBlock(ctx *TypeBlockContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitTypeLitBody(ctx *TypeLitBodyContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitTypeBlockBody(ctx *TypeBlockBodyContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitTypeStruct(ctx *TypeStructContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitTypeAlias(ctx *TypeAliasContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitTypeBlockStruct(ctx *TypeBlockStructContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitTypeBlockAlias(ctx *TypeBlockAliasContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitField(ctx *FieldContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitNormalField(ctx *NormalFieldContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitAnonymousFiled(ctx *AnonymousFiledContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitDataType(ctx *DataTypeContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitPointerType(ctx *PointerTypeContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitMapType(ctx *MapTypeContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitArrayType(ctx *ArrayTypeContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitServiceSpec(ctx *ServiceSpecContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitAtServer(ctx *AtServerContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitServiceApi(ctx *ServiceApiContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitServiceRoute(ctx *ServiceRouteContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitAtDoc(ctx *AtDocContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitAtHandler(ctx *AtHandlerContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitRoute(ctx *RouteContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitBody(ctx *BodyContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitReplybody(ctx *ReplybodyContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitKvLit(ctx *KvLitContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitServiceName(ctx *ServiceNameContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseApiParserVisitor) VisitPath(ctx *PathContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
234
tools/goctl/api/parser/g4/gen/api/apiparser_lexer.go
Normal file
234
tools/goctl/api/parser/g4/gen/api/apiparser_lexer.go
Normal file
@@ -0,0 +1,234 @@
|
||||
// Code generated from tools/goctl/api/parser/g4/ApiParser.g4 by ANTLR 4.9. DO NOT EDIT.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unicode"
|
||||
|
||||
"github.com/antlr/antlr4/runtime/Go/antlr"
|
||||
)
|
||||
|
||||
// Suppress unused import error
|
||||
var _ = fmt.Printf
|
||||
var _ = unicode.IsLetter
|
||||
|
||||
var serializedLexerAtn = []uint16{
|
||||
3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 25, 266,
|
||||
8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7,
|
||||
9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12,
|
||||
4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4,
|
||||
18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23,
|
||||
9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9,
|
||||
28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 3, 2, 3, 2, 3, 3, 3, 3, 3,
|
||||
4, 3, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3,
|
||||
8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11,
|
||||
3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3,
|
||||
15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16,
|
||||
3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3,
|
||||
17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 6, 18, 132,
|
||||
10, 18, 13, 18, 14, 18, 133, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19,
|
||||
7, 19, 142, 10, 19, 12, 19, 14, 19, 145, 11, 19, 3, 19, 3, 19, 3, 19, 3,
|
||||
19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 7, 20, 156, 10, 20, 12, 20, 14,
|
||||
20, 159, 11, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 7, 21, 166, 10, 21,
|
||||
12, 21, 14, 21, 169, 11, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 6, 22,
|
||||
176, 10, 22, 13, 22, 14, 22, 177, 3, 22, 3, 22, 3, 23, 3, 23, 7, 23, 184,
|
||||
10, 23, 12, 23, 14, 23, 187, 11, 23, 3, 23, 3, 23, 7, 23, 191, 10, 23,
|
||||
12, 23, 14, 23, 194, 11, 23, 5, 23, 196, 10, 23, 3, 24, 3, 24, 7, 24, 200,
|
||||
10, 24, 12, 24, 14, 24, 203, 11, 24, 3, 25, 3, 25, 5, 25, 207, 10, 25,
|
||||
3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 5, 26, 215, 10, 26, 3, 26, 5,
|
||||
26, 218, 10, 26, 3, 26, 3, 26, 3, 26, 6, 26, 223, 10, 26, 13, 26, 14, 26,
|
||||
224, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 5, 26, 232, 10, 26, 3, 27, 3, 27,
|
||||
3, 27, 7, 27, 237, 10, 27, 12, 27, 14, 27, 240, 11, 27, 3, 27, 5, 27, 243,
|
||||
10, 27, 3, 28, 3, 28, 3, 29, 3, 29, 7, 29, 249, 10, 29, 12, 29, 14, 29,
|
||||
252, 11, 29, 3, 29, 5, 29, 255, 10, 29, 3, 30, 3, 30, 5, 30, 259, 10, 30,
|
||||
3, 31, 3, 31, 3, 31, 3, 31, 5, 31, 265, 10, 31, 3, 143, 2, 32, 3, 3, 5,
|
||||
4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25,
|
||||
14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43,
|
||||
23, 45, 24, 47, 25, 49, 2, 51, 2, 53, 2, 55, 2, 57, 2, 59, 2, 61, 2, 3,
|
||||
2, 20, 5, 2, 11, 12, 14, 15, 34, 34, 4, 2, 12, 12, 15, 15, 4, 2, 36, 36,
|
||||
94, 94, 6, 2, 12, 12, 15, 15, 94, 94, 98, 98, 4, 2, 11, 11, 34, 34, 6,
|
||||
2, 12, 12, 15, 15, 36, 36, 98, 98, 4, 2, 71, 71, 103, 103, 4, 2, 45, 45,
|
||||
47, 47, 10, 2, 36, 36, 41, 41, 94, 94, 100, 100, 104, 104, 112, 112, 116,
|
||||
116, 118, 118, 3, 2, 50, 53, 3, 2, 50, 57, 5, 2, 50, 59, 67, 72, 99, 104,
|
||||
3, 2, 50, 59, 4, 2, 50, 59, 97, 97, 6, 2, 38, 38, 67, 92, 97, 97, 99, 124,
|
||||
4, 2, 2, 129, 55298, 56321, 3, 2, 55298, 56321, 3, 2, 56322, 57345, 2,
|
||||
283, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2,
|
||||
2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3,
|
||||
2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25,
|
||||
3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2,
|
||||
33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2,
|
||||
2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2,
|
||||
2, 3, 63, 3, 2, 2, 2, 5, 65, 3, 2, 2, 2, 7, 67, 3, 2, 2, 2, 9, 69, 3, 2,
|
||||
2, 2, 11, 71, 3, 2, 2, 2, 13, 73, 3, 2, 2, 2, 15, 75, 3, 2, 2, 2, 17, 85,
|
||||
3, 2, 2, 2, 19, 87, 3, 2, 2, 2, 21, 89, 3, 2, 2, 2, 23, 91, 3, 2, 2, 2,
|
||||
25, 93, 3, 2, 2, 2, 27, 96, 3, 2, 2, 2, 29, 101, 3, 2, 2, 2, 31, 110, 3,
|
||||
2, 2, 2, 33, 122, 3, 2, 2, 2, 35, 131, 3, 2, 2, 2, 37, 137, 3, 2, 2, 2,
|
||||
39, 151, 3, 2, 2, 2, 41, 162, 3, 2, 2, 2, 43, 172, 3, 2, 2, 2, 45, 181,
|
||||
3, 2, 2, 2, 47, 197, 3, 2, 2, 2, 49, 204, 3, 2, 2, 2, 51, 231, 3, 2, 2,
|
||||
2, 53, 233, 3, 2, 2, 2, 55, 244, 3, 2, 2, 2, 57, 246, 3, 2, 2, 2, 59, 258,
|
||||
3, 2, 2, 2, 61, 264, 3, 2, 2, 2, 63, 64, 7, 63, 2, 2, 64, 4, 3, 2, 2, 2,
|
||||
65, 66, 7, 42, 2, 2, 66, 6, 3, 2, 2, 2, 67, 68, 7, 43, 2, 2, 68, 8, 3,
|
||||
2, 2, 2, 69, 70, 7, 125, 2, 2, 70, 10, 3, 2, 2, 2, 71, 72, 7, 127, 2, 2,
|
||||
72, 12, 3, 2, 2, 2, 73, 74, 7, 44, 2, 2, 74, 14, 3, 2, 2, 2, 75, 76, 7,
|
||||
118, 2, 2, 76, 77, 7, 107, 2, 2, 77, 78, 7, 111, 2, 2, 78, 79, 7, 103,
|
||||
2, 2, 79, 80, 7, 48, 2, 2, 80, 81, 7, 86, 2, 2, 81, 82, 7, 107, 2, 2, 82,
|
||||
83, 7, 111, 2, 2, 83, 84, 7, 103, 2, 2, 84, 16, 3, 2, 2, 2, 85, 86, 7,
|
||||
93, 2, 2, 86, 18, 3, 2, 2, 2, 87, 88, 7, 95, 2, 2, 88, 20, 3, 2, 2, 2,
|
||||
89, 90, 7, 47, 2, 2, 90, 22, 3, 2, 2, 2, 91, 92, 7, 49, 2, 2, 92, 24, 3,
|
||||
2, 2, 2, 93, 94, 7, 49, 2, 2, 94, 95, 7, 60, 2, 2, 95, 26, 3, 2, 2, 2,
|
||||
96, 97, 7, 66, 2, 2, 97, 98, 7, 102, 2, 2, 98, 99, 7, 113, 2, 2, 99, 100,
|
||||
7, 101, 2, 2, 100, 28, 3, 2, 2, 2, 101, 102, 7, 66, 2, 2, 102, 103, 7,
|
||||
106, 2, 2, 103, 104, 7, 99, 2, 2, 104, 105, 7, 112, 2, 2, 105, 106, 7,
|
||||
102, 2, 2, 106, 107, 7, 110, 2, 2, 107, 108, 7, 103, 2, 2, 108, 109, 7,
|
||||
116, 2, 2, 109, 30, 3, 2, 2, 2, 110, 111, 7, 107, 2, 2, 111, 112, 7, 112,
|
||||
2, 2, 112, 113, 7, 118, 2, 2, 113, 114, 7, 103, 2, 2, 114, 115, 7, 116,
|
||||
2, 2, 115, 116, 7, 104, 2, 2, 116, 117, 7, 99, 2, 2, 117, 118, 7, 101,
|
||||
2, 2, 118, 119, 7, 103, 2, 2, 119, 120, 7, 125, 2, 2, 120, 121, 7, 127,
|
||||
2, 2, 121, 32, 3, 2, 2, 2, 122, 123, 7, 66, 2, 2, 123, 124, 7, 117, 2,
|
||||
2, 124, 125, 7, 103, 2, 2, 125, 126, 7, 116, 2, 2, 126, 127, 7, 120, 2,
|
||||
2, 127, 128, 7, 103, 2, 2, 128, 129, 7, 116, 2, 2, 129, 34, 3, 2, 2, 2,
|
||||
130, 132, 9, 2, 2, 2, 131, 130, 3, 2, 2, 2, 132, 133, 3, 2, 2, 2, 133,
|
||||
131, 3, 2, 2, 2, 133, 134, 3, 2, 2, 2, 134, 135, 3, 2, 2, 2, 135, 136,
|
||||
8, 18, 2, 2, 136, 36, 3, 2, 2, 2, 137, 138, 7, 49, 2, 2, 138, 139, 7, 44,
|
||||
2, 2, 139, 143, 3, 2, 2, 2, 140, 142, 11, 2, 2, 2, 141, 140, 3, 2, 2, 2,
|
||||
142, 145, 3, 2, 2, 2, 143, 144, 3, 2, 2, 2, 143, 141, 3, 2, 2, 2, 144,
|
||||
146, 3, 2, 2, 2, 145, 143, 3, 2, 2, 2, 146, 147, 7, 44, 2, 2, 147, 148,
|
||||
7, 49, 2, 2, 148, 149, 3, 2, 2, 2, 149, 150, 8, 19, 3, 2, 150, 38, 3, 2,
|
||||
2, 2, 151, 152, 7, 49, 2, 2, 152, 153, 7, 49, 2, 2, 153, 157, 3, 2, 2,
|
||||
2, 154, 156, 10, 3, 2, 2, 155, 154, 3, 2, 2, 2, 156, 159, 3, 2, 2, 2, 157,
|
||||
155, 3, 2, 2, 2, 157, 158, 3, 2, 2, 2, 158, 160, 3, 2, 2, 2, 159, 157,
|
||||
3, 2, 2, 2, 160, 161, 8, 20, 3, 2, 161, 40, 3, 2, 2, 2, 162, 167, 7, 36,
|
||||
2, 2, 163, 166, 10, 4, 2, 2, 164, 166, 5, 51, 26, 2, 165, 163, 3, 2, 2,
|
||||
2, 165, 164, 3, 2, 2, 2, 166, 169, 3, 2, 2, 2, 167, 165, 3, 2, 2, 2, 167,
|
||||
168, 3, 2, 2, 2, 168, 170, 3, 2, 2, 2, 169, 167, 3, 2, 2, 2, 170, 171,
|
||||
7, 36, 2, 2, 171, 42, 3, 2, 2, 2, 172, 175, 7, 98, 2, 2, 173, 176, 10,
|
||||
5, 2, 2, 174, 176, 5, 51, 26, 2, 175, 173, 3, 2, 2, 2, 175, 174, 3, 2,
|
||||
2, 2, 176, 177, 3, 2, 2, 2, 177, 175, 3, 2, 2, 2, 177, 178, 3, 2, 2, 2,
|
||||
178, 179, 3, 2, 2, 2, 179, 180, 7, 98, 2, 2, 180, 44, 3, 2, 2, 2, 181,
|
||||
185, 7, 60, 2, 2, 182, 184, 9, 6, 2, 2, 183, 182, 3, 2, 2, 2, 184, 187,
|
||||
3, 2, 2, 2, 185, 183, 3, 2, 2, 2, 185, 186, 3, 2, 2, 2, 186, 195, 3, 2,
|
||||
2, 2, 187, 185, 3, 2, 2, 2, 188, 196, 5, 41, 21, 2, 189, 191, 10, 7, 2,
|
||||
2, 190, 189, 3, 2, 2, 2, 191, 194, 3, 2, 2, 2, 192, 190, 3, 2, 2, 2, 192,
|
||||
193, 3, 2, 2, 2, 193, 196, 3, 2, 2, 2, 194, 192, 3, 2, 2, 2, 195, 188,
|
||||
3, 2, 2, 2, 195, 192, 3, 2, 2, 2, 196, 46, 3, 2, 2, 2, 197, 201, 5, 61,
|
||||
31, 2, 198, 200, 5, 59, 30, 2, 199, 198, 3, 2, 2, 2, 200, 203, 3, 2, 2,
|
||||
2, 201, 199, 3, 2, 2, 2, 201, 202, 3, 2, 2, 2, 202, 48, 3, 2, 2, 2, 203,
|
||||
201, 3, 2, 2, 2, 204, 206, 9, 8, 2, 2, 205, 207, 9, 9, 2, 2, 206, 205,
|
||||
3, 2, 2, 2, 206, 207, 3, 2, 2, 2, 207, 208, 3, 2, 2, 2, 208, 209, 5, 57,
|
||||
29, 2, 209, 50, 3, 2, 2, 2, 210, 211, 7, 94, 2, 2, 211, 232, 9, 10, 2,
|
||||
2, 212, 217, 7, 94, 2, 2, 213, 215, 9, 11, 2, 2, 214, 213, 3, 2, 2, 2,
|
||||
214, 215, 3, 2, 2, 2, 215, 216, 3, 2, 2, 2, 216, 218, 9, 12, 2, 2, 217,
|
||||
214, 3, 2, 2, 2, 217, 218, 3, 2, 2, 2, 218, 219, 3, 2, 2, 2, 219, 232,
|
||||
9, 12, 2, 2, 220, 222, 7, 94, 2, 2, 221, 223, 7, 119, 2, 2, 222, 221, 3,
|
||||
2, 2, 2, 223, 224, 3, 2, 2, 2, 224, 222, 3, 2, 2, 2, 224, 225, 3, 2, 2,
|
||||
2, 225, 226, 3, 2, 2, 2, 226, 227, 5, 55, 28, 2, 227, 228, 5, 55, 28, 2,
|
||||
228, 229, 5, 55, 28, 2, 229, 230, 5, 55, 28, 2, 230, 232, 3, 2, 2, 2, 231,
|
||||
210, 3, 2, 2, 2, 231, 212, 3, 2, 2, 2, 231, 220, 3, 2, 2, 2, 232, 52, 3,
|
||||
2, 2, 2, 233, 242, 5, 55, 28, 2, 234, 237, 5, 55, 28, 2, 235, 237, 7, 97,
|
||||
2, 2, 236, 234, 3, 2, 2, 2, 236, 235, 3, 2, 2, 2, 237, 240, 3, 2, 2, 2,
|
||||
238, 236, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 241, 3, 2, 2, 2, 240,
|
||||
238, 3, 2, 2, 2, 241, 243, 5, 55, 28, 2, 242, 238, 3, 2, 2, 2, 242, 243,
|
||||
3, 2, 2, 2, 243, 54, 3, 2, 2, 2, 244, 245, 9, 13, 2, 2, 245, 56, 3, 2,
|
||||
2, 2, 246, 254, 9, 14, 2, 2, 247, 249, 9, 15, 2, 2, 248, 247, 3, 2, 2,
|
||||
2, 249, 252, 3, 2, 2, 2, 250, 248, 3, 2, 2, 2, 250, 251, 3, 2, 2, 2, 251,
|
||||
253, 3, 2, 2, 2, 252, 250, 3, 2, 2, 2, 253, 255, 9, 14, 2, 2, 254, 250,
|
||||
3, 2, 2, 2, 254, 255, 3, 2, 2, 2, 255, 58, 3, 2, 2, 2, 256, 259, 5, 61,
|
||||
31, 2, 257, 259, 9, 14, 2, 2, 258, 256, 3, 2, 2, 2, 258, 257, 3, 2, 2,
|
||||
2, 259, 60, 3, 2, 2, 2, 260, 265, 9, 16, 2, 2, 261, 265, 10, 17, 2, 2,
|
||||
262, 263, 9, 18, 2, 2, 263, 265, 9, 19, 2, 2, 264, 260, 3, 2, 2, 2, 264,
|
||||
261, 3, 2, 2, 2, 264, 262, 3, 2, 2, 2, 265, 62, 3, 2, 2, 2, 26, 2, 133,
|
||||
143, 157, 165, 167, 175, 177, 185, 192, 195, 201, 206, 214, 217, 224, 231,
|
||||
236, 238, 242, 250, 254, 258, 264, 4, 2, 3, 2, 2, 90, 2,
|
||||
}
|
||||
|
||||
var lexerChannelNames = []string{
|
||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN",
|
||||
}
|
||||
|
||||
var lexerModeNames = []string{
|
||||
"DEFAULT_MODE",
|
||||
}
|
||||
|
||||
var lexerLiteralNames = []string{
|
||||
"", "'='", "'('", "')'", "'{'", "'}'", "'*'", "'time.Time'", "'['", "']'",
|
||||
"'-'", "'/'", "'/:'", "'@doc'", "'@handler'", "'interface{}'", "'@server'",
|
||||
}
|
||||
|
||||
var lexerSymbolicNames = []string{
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "ATDOC", "ATHANDLER",
|
||||
"INTERFACE", "ATSERVER", "WS", "COMMENT", "LINE_COMMENT", "STRING", "RAW_STRING",
|
||||
"LINE_VALUE", "ID",
|
||||
}
|
||||
|
||||
var lexerRuleNames = []string{
|
||||
"T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8",
|
||||
"T__9", "T__10", "T__11", "ATDOC", "ATHANDLER", "INTERFACE", "ATSERVER",
|
||||
"WS", "COMMENT", "LINE_COMMENT", "STRING", "RAW_STRING", "LINE_VALUE",
|
||||
"ID", "ExponentPart", "EscapeSequence", "HexDigits", "HexDigit", "Digits",
|
||||
"LetterOrDigit", "Letter",
|
||||
}
|
||||
|
||||
type ApiParserLexer struct {
|
||||
*antlr.BaseLexer
|
||||
channelNames []string
|
||||
modeNames []string
|
||||
// TODO: EOF string
|
||||
}
|
||||
|
||||
// NewApiParserLexer produces a new lexer instance for the optional input antlr.CharStream.
|
||||
//
|
||||
// The *ApiParserLexer instance produced may be reused by calling the SetInputStream method.
|
||||
// The initial lexer configuration is expensive to construct, and the object is not thread-safe;
|
||||
// however, if used within a Golang sync.Pool, the construction cost amortizes well and the
|
||||
// objects can be used in a thread-safe manner.
|
||||
func NewApiParserLexer(input antlr.CharStream) *ApiParserLexer {
|
||||
l := new(ApiParserLexer)
|
||||
lexerDeserializer := antlr.NewATNDeserializer(nil)
|
||||
lexerAtn := lexerDeserializer.DeserializeFromUInt16(serializedLexerAtn)
|
||||
lexerDecisionToDFA := make([]*antlr.DFA, len(lexerAtn.DecisionToState))
|
||||
for index, ds := range lexerAtn.DecisionToState {
|
||||
lexerDecisionToDFA[index] = antlr.NewDFA(ds, index)
|
||||
}
|
||||
l.BaseLexer = antlr.NewBaseLexer(input)
|
||||
l.Interpreter = antlr.NewLexerATNSimulator(l, lexerAtn, lexerDecisionToDFA, antlr.NewPredictionContextCache())
|
||||
|
||||
l.channelNames = lexerChannelNames
|
||||
l.modeNames = lexerModeNames
|
||||
l.RuleNames = lexerRuleNames
|
||||
l.LiteralNames = lexerLiteralNames
|
||||
l.SymbolicNames = lexerSymbolicNames
|
||||
l.GrammarFileName = "ApiParser.g4"
|
||||
// TODO: l.EOF = antlr.TokenEOF
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
// ApiParserLexer tokens.
|
||||
const (
|
||||
ApiParserLexerT__0 = 1
|
||||
ApiParserLexerT__1 = 2
|
||||
ApiParserLexerT__2 = 3
|
||||
ApiParserLexerT__3 = 4
|
||||
ApiParserLexerT__4 = 5
|
||||
ApiParserLexerT__5 = 6
|
||||
ApiParserLexerT__6 = 7
|
||||
ApiParserLexerT__7 = 8
|
||||
ApiParserLexerT__8 = 9
|
||||
ApiParserLexerT__9 = 10
|
||||
ApiParserLexerT__10 = 11
|
||||
ApiParserLexerT__11 = 12
|
||||
ApiParserLexerATDOC = 13
|
||||
ApiParserLexerATHANDLER = 14
|
||||
ApiParserLexerINTERFACE = 15
|
||||
ApiParserLexerATSERVER = 16
|
||||
ApiParserLexerWS = 17
|
||||
ApiParserLexerCOMMENT = 18
|
||||
ApiParserLexerLINE_COMMENT = 19
|
||||
ApiParserLexerSTRING = 20
|
||||
ApiParserLexerRAW_STRING = 21
|
||||
ApiParserLexerLINE_VALUE = 22
|
||||
ApiParserLexerID = 23
|
||||
)
|
||||
|
||||
const COMEMNTS = 88
|
||||
5688
tools/goctl/api/parser/g4/gen/api/apiparser_parser.go
Normal file
5688
tools/goctl/api/parser/g4/gen/api/apiparser_parser.go
Normal file
File diff suppressed because it is too large
Load Diff
120
tools/goctl/api/parser/g4/gen/api/apiparser_visitor.go
Normal file
120
tools/goctl/api/parser/g4/gen/api/apiparser_visitor.go
Normal file
@@ -0,0 +1,120 @@
|
||||
// Code generated from tools/goctl/api/parser/g4/ApiParser.g4 by ANTLR 4.9. DO NOT EDIT.
|
||||
|
||||
package api // ApiParser
|
||||
import "github.com/antlr/antlr4/runtime/Go/antlr"
|
||||
|
||||
// A complete Visitor for a parse tree produced by ApiParserParser.
|
||||
type ApiParserVisitor interface {
|
||||
antlr.ParseTreeVisitor
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#api.
|
||||
VisitApi(ctx *ApiContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#spec.
|
||||
VisitSpec(ctx *SpecContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#syntaxLit.
|
||||
VisitSyntaxLit(ctx *SyntaxLitContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#importSpec.
|
||||
VisitImportSpec(ctx *ImportSpecContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#importLit.
|
||||
VisitImportLit(ctx *ImportLitContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#importBlock.
|
||||
VisitImportBlock(ctx *ImportBlockContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#importBlockValue.
|
||||
VisitImportBlockValue(ctx *ImportBlockValueContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#importValue.
|
||||
VisitImportValue(ctx *ImportValueContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#infoSpec.
|
||||
VisitInfoSpec(ctx *InfoSpecContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#typeSpec.
|
||||
VisitTypeSpec(ctx *TypeSpecContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#typeLit.
|
||||
VisitTypeLit(ctx *TypeLitContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#typeBlock.
|
||||
VisitTypeBlock(ctx *TypeBlockContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#typeLitBody.
|
||||
VisitTypeLitBody(ctx *TypeLitBodyContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#typeBlockBody.
|
||||
VisitTypeBlockBody(ctx *TypeBlockBodyContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#typeStruct.
|
||||
VisitTypeStruct(ctx *TypeStructContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#typeAlias.
|
||||
VisitTypeAlias(ctx *TypeAliasContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#typeBlockStruct.
|
||||
VisitTypeBlockStruct(ctx *TypeBlockStructContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#typeBlockAlias.
|
||||
VisitTypeBlockAlias(ctx *TypeBlockAliasContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#field.
|
||||
VisitField(ctx *FieldContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#normalField.
|
||||
VisitNormalField(ctx *NormalFieldContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#anonymousFiled.
|
||||
VisitAnonymousFiled(ctx *AnonymousFiledContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#dataType.
|
||||
VisitDataType(ctx *DataTypeContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#pointerType.
|
||||
VisitPointerType(ctx *PointerTypeContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#mapType.
|
||||
VisitMapType(ctx *MapTypeContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#arrayType.
|
||||
VisitArrayType(ctx *ArrayTypeContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#serviceSpec.
|
||||
VisitServiceSpec(ctx *ServiceSpecContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#atServer.
|
||||
VisitAtServer(ctx *AtServerContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#serviceApi.
|
||||
VisitServiceApi(ctx *ServiceApiContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#serviceRoute.
|
||||
VisitServiceRoute(ctx *ServiceRouteContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#atDoc.
|
||||
VisitAtDoc(ctx *AtDocContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#atHandler.
|
||||
VisitAtHandler(ctx *AtHandlerContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#route.
|
||||
VisitRoute(ctx *RouteContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#body.
|
||||
VisitBody(ctx *BodyContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#replybody.
|
||||
VisitReplybody(ctx *ReplybodyContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#kvLit.
|
||||
VisitKvLit(ctx *KvLitContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#serviceName.
|
||||
VisitServiceName(ctx *ServiceNameContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by ApiParserParser#path.
|
||||
VisitPath(ctx *PathContext) interface{}
|
||||
}
|
||||
222
tools/goctl/api/parser/g4/gen/api/baseparser.go
Normal file
222
tools/goctl/api/parser/g4/gen/api/baseparser.go
Normal file
@@ -0,0 +1,222 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/antlr/antlr4/runtime/Go/antlr"
|
||||
)
|
||||
|
||||
const (
|
||||
versionRegex = `(?m)"v[1-9][0-9]*"`
|
||||
importValueRegex = `(?m)"(/?[a-zA-Z0-9_#-])+\.api"`
|
||||
tagRegex = `(?m)\x60[a-z]+:".+"\x60`
|
||||
)
|
||||
|
||||
var holder = struct{}{}
|
||||
var kind = map[string]struct{}{
|
||||
"bool": holder,
|
||||
"int": holder,
|
||||
"int8": holder,
|
||||
"int16": holder,
|
||||
"int32": holder,
|
||||
"int64": holder,
|
||||
"uint": holder,
|
||||
"uint8": holder,
|
||||
"uint16": holder,
|
||||
"uint32": holder,
|
||||
"uint64": holder,
|
||||
"uintptr": holder,
|
||||
"float32": holder,
|
||||
"float64": holder,
|
||||
"complex64": holder,
|
||||
"complex128": holder,
|
||||
"string": holder,
|
||||
"byte": holder,
|
||||
"rune": holder,
|
||||
}
|
||||
|
||||
func match(p *ApiParserParser, text string) {
|
||||
v := getCurrentTokenText(p)
|
||||
|
||||
if v != text {
|
||||
notifyErrorListeners(p, expecting(text, v))
|
||||
}
|
||||
}
|
||||
|
||||
func checkVersion(p *ApiParserParser) {
|
||||
v := getCurrentTokenText(p)
|
||||
if !matchRegex(v, versionRegex) {
|
||||
notifyErrorListeners(p, mismatched("version", v))
|
||||
}
|
||||
}
|
||||
|
||||
func checkImportValue(p *ApiParserParser) {
|
||||
v := getCurrentTokenText(p)
|
||||
if !matchRegex(v, importValueRegex) {
|
||||
notifyErrorListeners(p, mismatched("import value", v))
|
||||
}
|
||||
}
|
||||
|
||||
func checkKeyValue(p *ApiParserParser) {
|
||||
v := getCurrentTokenText(p)
|
||||
if !strings.HasPrefix(v, ":") {
|
||||
notifyErrorListeners(p, mismatched(":", v))
|
||||
}
|
||||
|
||||
v = strings.TrimPrefix(v, ":")
|
||||
v = strings.TrimFunc(v, func(r rune) bool {
|
||||
return unicode.IsSpace(r)
|
||||
})
|
||||
setCurrentTokenText(p, v)
|
||||
}
|
||||
|
||||
func checkHttpMethod(p *ApiParserParser) {
|
||||
method := getCurrentTokenText(p)
|
||||
uppler := strings.ToUpper(method)
|
||||
switch uppler {
|
||||
case http.MethodPost, http.MethodGet, http.MethodHead,
|
||||
http.MethodPut, http.MethodPatch, http.MethodDelete,
|
||||
http.MethodConnect, http.MethodOptions, http.MethodTrace:
|
||||
if method != strings.ToLower(method) {
|
||||
notifyErrorListeners(p, expecting("http method lower case", method))
|
||||
}
|
||||
default:
|
||||
notifyErrorListeners(p, expecting("http method", method))
|
||||
}
|
||||
}
|
||||
|
||||
func checkKeyword(p *ApiParserParser) {
|
||||
v := getCurrentTokenText(p)
|
||||
if IsGolangKeyWord(v) {
|
||||
notifyErrorListeners(p, fmt.Sprintf("expecting ID, found golang keyword: '%s'", v))
|
||||
}
|
||||
}
|
||||
|
||||
func checkKey(p *ApiParserParser) {
|
||||
v := getCurrentTokenText(p)
|
||||
if IsGolangKeyWord(v) {
|
||||
notifyErrorListeners(p, fmt.Sprintf("expecting ID, found golang keyword: '%s'", v))
|
||||
}
|
||||
|
||||
if _, ok := kind[v]; !ok {
|
||||
notifyErrorListeners(p, fmt.Sprintf("expecting golang basic type, found : '%s'", v))
|
||||
}
|
||||
}
|
||||
|
||||
func IsBasicType(text string) bool {
|
||||
_, ok := kind[text]
|
||||
return ok
|
||||
}
|
||||
|
||||
func IsGolangKeyWord(text string, excepts ...string) bool {
|
||||
for _, each := range excepts {
|
||||
if text == each {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
switch text {
|
||||
case "var", "const", "package", "import", "func", "return",
|
||||
"defer", "go", "select", "interface", "struct", "break", "case",
|
||||
"continue", "for", "fallthrough", "else", "if", "switch", "goto",
|
||||
"default", "chan", "type", "map", "range":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func isNormal(p *ApiParserParser) bool {
|
||||
ct := p.GetTokenStream().(*antlr.CommonTokenStream)
|
||||
line := p.GetCurrentToken().GetLine()
|
||||
tokens := ct.GetAllTokens()
|
||||
var list []string
|
||||
for _, token := range tokens {
|
||||
if token.GetLine() == line {
|
||||
text := token.GetText()
|
||||
if strings.HasPrefix(text, "//") {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(text, "/*") {
|
||||
continue
|
||||
}
|
||||
if text == "<EOF>" {
|
||||
continue
|
||||
}
|
||||
if strings.TrimSpace(text) == "" {
|
||||
continue
|
||||
}
|
||||
list = append(list, text)
|
||||
}
|
||||
}
|
||||
if len(list) == 1 {
|
||||
t := strings.TrimPrefix(list[0], "*")
|
||||
if IsGolangKeyWord(t) {
|
||||
notifyErrorListeners(p, fmt.Sprintf("expecting ID, found golang keyword: '%s'", t))
|
||||
}
|
||||
}
|
||||
if len(list) > 1 {
|
||||
if list[0] == "*" {
|
||||
t := strings.TrimPrefix(list[1], "*")
|
||||
if IsGolangKeyWord(t) {
|
||||
notifyErrorListeners(p, fmt.Sprintf("expecting ID, found golang keyword: '%s'", t))
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
return len(list) > 1
|
||||
}
|
||||
|
||||
func MatchTag(v string) bool {
|
||||
return matchRegex(v, tagRegex)
|
||||
}
|
||||
|
||||
func isInterface(p *ApiParserParser) {
|
||||
v := getCurrentTokenText(p)
|
||||
if IsGolangKeyWord(v) {
|
||||
notifyErrorListeners(p, fmt.Sprintf("expecting ID, found golang keyword: '%s'", v))
|
||||
}
|
||||
}
|
||||
|
||||
func getCurrentTokenText(p *ApiParserParser) string {
|
||||
token := p.GetCurrentToken()
|
||||
if token == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return token.GetText()
|
||||
}
|
||||
|
||||
func setCurrentTokenText(p *ApiParserParser, text string) {
|
||||
token := p.GetCurrentToken()
|
||||
if token == nil {
|
||||
return
|
||||
}
|
||||
|
||||
token.SetText(text)
|
||||
}
|
||||
|
||||
func notifyErrorListeners(p *ApiParserParser, msg string) {
|
||||
p.NotifyErrorListeners(msg, nil, nil)
|
||||
}
|
||||
|
||||
func matchRegex(text, str string) bool {
|
||||
re := regexp.MustCompile(str)
|
||||
v := re.FindString(text)
|
||||
text = strings.TrimFunc(text, func(r rune) bool {
|
||||
return unicode.IsSpace(r)
|
||||
})
|
||||
return v == text
|
||||
}
|
||||
|
||||
func expecting(expecting, found string) string {
|
||||
return fmt.Sprintf(`expecting '%s', found input '%s'`, expecting, found)
|
||||
}
|
||||
|
||||
func mismatched(expecting, found string) string {
|
||||
return fmt.Sprintf(`mismatched '%s', found input '%s'`, expecting, found)
|
||||
}
|
||||
11
tools/goctl/api/parser/g4/gen/api/baseparser_test.go
Normal file
11
tools/goctl/api/parser/g4/gen/api/baseparser_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMatch(t *testing.T) {
|
||||
assert.False(t, matchRegex("v1ddd", versionRegex))
|
||||
}
|
||||
Reference in New Issue
Block a user