forked from ebhomengo/niki
568 lines
13 KiB
Go
568 lines
13 KiB
Go
|
package swag
|
||
|
|
||
|
import (
|
||
|
"go/ast"
|
||
|
"go/token"
|
||
|
"reflect"
|
||
|
"strconv"
|
||
|
"strings"
|
||
|
"unicode/utf8"
|
||
|
)
|
||
|
|
||
|
// ConstVariable a model to record a const variable
|
||
|
type ConstVariable struct {
|
||
|
Name *ast.Ident
|
||
|
Type ast.Expr
|
||
|
Value interface{}
|
||
|
Comment *ast.CommentGroup
|
||
|
File *ast.File
|
||
|
Pkg *PackageDefinitions
|
||
|
}
|
||
|
|
||
|
var escapedChars = map[uint8]uint8{
|
||
|
'n': '\n',
|
||
|
'r': '\r',
|
||
|
't': '\t',
|
||
|
'v': '\v',
|
||
|
'\\': '\\',
|
||
|
'"': '"',
|
||
|
}
|
||
|
|
||
|
// EvaluateEscapedChar parse escaped character
|
||
|
func EvaluateEscapedChar(text string) rune {
|
||
|
if len(text) == 1 {
|
||
|
return rune(text[0])
|
||
|
}
|
||
|
|
||
|
if len(text) == 2 && text[0] == '\\' {
|
||
|
return rune(escapedChars[text[1]])
|
||
|
}
|
||
|
|
||
|
if len(text) == 6 && text[0:2] == "\\u" {
|
||
|
n, err := strconv.ParseInt(text[2:], 16, 32)
|
||
|
if err == nil {
|
||
|
return rune(n)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
// EvaluateEscapedString parse escaped characters in string
|
||
|
func EvaluateEscapedString(text string) string {
|
||
|
if !strings.ContainsRune(text, '\\') {
|
||
|
return text
|
||
|
}
|
||
|
result := make([]byte, 0, len(text))
|
||
|
for i := 0; i < len(text); i++ {
|
||
|
if text[i] == '\\' {
|
||
|
i++
|
||
|
if text[i] == 'u' {
|
||
|
i++
|
||
|
char, err := strconv.ParseInt(text[i:i+4], 16, 32)
|
||
|
if err == nil {
|
||
|
result = utf8.AppendRune(result, rune(char))
|
||
|
}
|
||
|
i += 3
|
||
|
} else if c, ok := escapedChars[text[i]]; ok {
|
||
|
result = append(result, c)
|
||
|
}
|
||
|
} else {
|
||
|
result = append(result, text[i])
|
||
|
}
|
||
|
}
|
||
|
return string(result)
|
||
|
}
|
||
|
|
||
|
// EvaluateDataConversion evaluate the type a explicit type conversion
|
||
|
func EvaluateDataConversion(x interface{}, typeName string) interface{} {
|
||
|
switch value := x.(type) {
|
||
|
case int:
|
||
|
switch typeName {
|
||
|
case "int":
|
||
|
return int(value)
|
||
|
case "byte":
|
||
|
return byte(value)
|
||
|
case "int8":
|
||
|
return int8(value)
|
||
|
case "int16":
|
||
|
return int16(value)
|
||
|
case "int32":
|
||
|
return int32(value)
|
||
|
case "int64":
|
||
|
return int64(value)
|
||
|
case "uint":
|
||
|
return uint(value)
|
||
|
case "uint8":
|
||
|
return uint8(value)
|
||
|
case "uint16":
|
||
|
return uint16(value)
|
||
|
case "uint32":
|
||
|
return uint32(value)
|
||
|
case "uint64":
|
||
|
return uint64(value)
|
||
|
case "rune":
|
||
|
return rune(value)
|
||
|
}
|
||
|
case uint:
|
||
|
switch typeName {
|
||
|
case "int":
|
||
|
return int(value)
|
||
|
case "byte":
|
||
|
return byte(value)
|
||
|
case "int8":
|
||
|
return int8(value)
|
||
|
case "int16":
|
||
|
return int16(value)
|
||
|
case "int32":
|
||
|
return int32(value)
|
||
|
case "int64":
|
||
|
return int64(value)
|
||
|
case "uint":
|
||
|
return uint(value)
|
||
|
case "uint8":
|
||
|
return uint8(value)
|
||
|
case "uint16":
|
||
|
return uint16(value)
|
||
|
case "uint32":
|
||
|
return uint32(value)
|
||
|
case "uint64":
|
||
|
return uint64(value)
|
||
|
case "rune":
|
||
|
return rune(value)
|
||
|
}
|
||
|
case int8:
|
||
|
switch typeName {
|
||
|
case "int":
|
||
|
return int(value)
|
||
|
case "byte":
|
||
|
return byte(value)
|
||
|
case "int8":
|
||
|
return int8(value)
|
||
|
case "int16":
|
||
|
return int16(value)
|
||
|
case "int32":
|
||
|
return int32(value)
|
||
|
case "int64":
|
||
|
return int64(value)
|
||
|
case "uint":
|
||
|
return uint(value)
|
||
|
case "uint8":
|
||
|
return uint8(value)
|
||
|
case "uint16":
|
||
|
return uint16(value)
|
||
|
case "uint32":
|
||
|
return uint32(value)
|
||
|
case "uint64":
|
||
|
return uint64(value)
|
||
|
case "rune":
|
||
|
return rune(value)
|
||
|
}
|
||
|
case uint8:
|
||
|
switch typeName {
|
||
|
case "int":
|
||
|
return int(value)
|
||
|
case "byte":
|
||
|
return byte(value)
|
||
|
case "int8":
|
||
|
return int8(value)
|
||
|
case "int16":
|
||
|
return int16(value)
|
||
|
case "int32":
|
||
|
return int32(value)
|
||
|
case "int64":
|
||
|
return int64(value)
|
||
|
case "uint":
|
||
|
return uint(value)
|
||
|
case "uint8":
|
||
|
return uint8(value)
|
||
|
case "uint16":
|
||
|
return uint16(value)
|
||
|
case "uint32":
|
||
|
return uint32(value)
|
||
|
case "uint64":
|
||
|
return uint64(value)
|
||
|
case "rune":
|
||
|
return rune(value)
|
||
|
}
|
||
|
case int16:
|
||
|
switch typeName {
|
||
|
case "int":
|
||
|
return int(value)
|
||
|
case "byte":
|
||
|
return byte(value)
|
||
|
case "int8":
|
||
|
return int8(value)
|
||
|
case "int16":
|
||
|
return int16(value)
|
||
|
case "int32":
|
||
|
return int32(value)
|
||
|
case "int64":
|
||
|
return int64(value)
|
||
|
case "uint":
|
||
|
return uint(value)
|
||
|
case "uint8":
|
||
|
return uint8(value)
|
||
|
case "uint16":
|
||
|
return uint16(value)
|
||
|
case "uint32":
|
||
|
return uint32(value)
|
||
|
case "uint64":
|
||
|
return uint64(value)
|
||
|
case "rune":
|
||
|
return rune(value)
|
||
|
}
|
||
|
case uint16:
|
||
|
switch typeName {
|
||
|
case "int":
|
||
|
return int(value)
|
||
|
case "byte":
|
||
|
return byte(value)
|
||
|
case "int8":
|
||
|
return int8(value)
|
||
|
case "int16":
|
||
|
return int16(value)
|
||
|
case "int32":
|
||
|
return int32(value)
|
||
|
case "int64":
|
||
|
return int64(value)
|
||
|
case "uint":
|
||
|
return uint(value)
|
||
|
case "uint8":
|
||
|
return uint8(value)
|
||
|
case "uint16":
|
||
|
return uint16(value)
|
||
|
case "uint32":
|
||
|
return uint32(value)
|
||
|
case "uint64":
|
||
|
return uint64(value)
|
||
|
case "rune":
|
||
|
return rune(value)
|
||
|
}
|
||
|
case int32:
|
||
|
switch typeName {
|
||
|
case "int":
|
||
|
return int(value)
|
||
|
case "byte":
|
||
|
return byte(value)
|
||
|
case "int8":
|
||
|
return int8(value)
|
||
|
case "int16":
|
||
|
return int16(value)
|
||
|
case "int32":
|
||
|
return int32(value)
|
||
|
case "int64":
|
||
|
return int64(value)
|
||
|
case "uint":
|
||
|
return uint(value)
|
||
|
case "uint8":
|
||
|
return uint8(value)
|
||
|
case "uint16":
|
||
|
return uint16(value)
|
||
|
case "uint32":
|
||
|
return uint32(value)
|
||
|
case "uint64":
|
||
|
return uint64(value)
|
||
|
case "rune":
|
||
|
return rune(value)
|
||
|
case "string":
|
||
|
return string(value)
|
||
|
}
|
||
|
case uint32:
|
||
|
switch typeName {
|
||
|
case "int":
|
||
|
return int(value)
|
||
|
case "byte":
|
||
|
return byte(value)
|
||
|
case "int8":
|
||
|
return int8(value)
|
||
|
case "int16":
|
||
|
return int16(value)
|
||
|
case "int32":
|
||
|
return int32(value)
|
||
|
case "int64":
|
||
|
return int64(value)
|
||
|
case "uint":
|
||
|
return uint(value)
|
||
|
case "uint8":
|
||
|
return uint8(value)
|
||
|
case "uint16":
|
||
|
return uint16(value)
|
||
|
case "uint32":
|
||
|
return uint32(value)
|
||
|
case "uint64":
|
||
|
return uint64(value)
|
||
|
case "rune":
|
||
|
return rune(value)
|
||
|
}
|
||
|
case int64:
|
||
|
switch typeName {
|
||
|
case "int":
|
||
|
return int(value)
|
||
|
case "byte":
|
||
|
return byte(value)
|
||
|
case "int8":
|
||
|
return int8(value)
|
||
|
case "int16":
|
||
|
return int16(value)
|
||
|
case "int32":
|
||
|
return int32(value)
|
||
|
case "int64":
|
||
|
return int64(value)
|
||
|
case "uint":
|
||
|
return uint(value)
|
||
|
case "uint8":
|
||
|
return uint8(value)
|
||
|
case "uint16":
|
||
|
return uint16(value)
|
||
|
case "uint32":
|
||
|
return uint32(value)
|
||
|
case "uint64":
|
||
|
return uint64(value)
|
||
|
case "rune":
|
||
|
return rune(value)
|
||
|
}
|
||
|
case uint64:
|
||
|
switch typeName {
|
||
|
case "int":
|
||
|
return int(value)
|
||
|
case "byte":
|
||
|
return byte(value)
|
||
|
case "int8":
|
||
|
return int8(value)
|
||
|
case "int16":
|
||
|
return int16(value)
|
||
|
case "int32":
|
||
|
return int32(value)
|
||
|
case "int64":
|
||
|
return int64(value)
|
||
|
case "uint":
|
||
|
return uint(value)
|
||
|
case "uint8":
|
||
|
return uint8(value)
|
||
|
case "uint16":
|
||
|
return uint16(value)
|
||
|
case "uint32":
|
||
|
return uint32(value)
|
||
|
case "uint64":
|
||
|
return uint64(value)
|
||
|
case "rune":
|
||
|
return rune(value)
|
||
|
}
|
||
|
case string:
|
||
|
switch typeName {
|
||
|
case "string":
|
||
|
return value
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// EvaluateUnary evaluate the type and value of a unary expression
|
||
|
func EvaluateUnary(x interface{}, operator token.Token, xtype ast.Expr) (interface{}, ast.Expr) {
|
||
|
switch operator {
|
||
|
case token.SUB:
|
||
|
switch value := x.(type) {
|
||
|
case int:
|
||
|
return -value, xtype
|
||
|
case int8:
|
||
|
return -value, xtype
|
||
|
case int16:
|
||
|
return -value, xtype
|
||
|
case int32:
|
||
|
return -value, xtype
|
||
|
case int64:
|
||
|
return -value, xtype
|
||
|
}
|
||
|
case token.XOR:
|
||
|
switch value := x.(type) {
|
||
|
case int:
|
||
|
return ^value, xtype
|
||
|
case int8:
|
||
|
return ^value, xtype
|
||
|
case int16:
|
||
|
return ^value, xtype
|
||
|
case int32:
|
||
|
return ^value, xtype
|
||
|
case int64:
|
||
|
return ^value, xtype
|
||
|
case uint:
|
||
|
return ^value, xtype
|
||
|
case uint8:
|
||
|
return ^value, xtype
|
||
|
case uint16:
|
||
|
return ^value, xtype
|
||
|
case uint32:
|
||
|
return ^value, xtype
|
||
|
case uint64:
|
||
|
return ^value, xtype
|
||
|
}
|
||
|
}
|
||
|
return nil, nil
|
||
|
}
|
||
|
|
||
|
// EvaluateBinary evaluate the type and value of a binary expression
|
||
|
func EvaluateBinary(x, y interface{}, operator token.Token, xtype, ytype ast.Expr) (interface{}, ast.Expr) {
|
||
|
if operator == token.SHR || operator == token.SHL {
|
||
|
var rightOperand uint64
|
||
|
yValue := reflect.ValueOf(y)
|
||
|
if yValue.CanUint() {
|
||
|
rightOperand = yValue.Uint()
|
||
|
} else if yValue.CanInt() {
|
||
|
rightOperand = uint64(yValue.Int())
|
||
|
}
|
||
|
|
||
|
switch operator {
|
||
|
case token.SHL:
|
||
|
switch xValue := x.(type) {
|
||
|
case int:
|
||
|
return xValue << rightOperand, xtype
|
||
|
case int8:
|
||
|
return xValue << rightOperand, xtype
|
||
|
case int16:
|
||
|
return xValue << rightOperand, xtype
|
||
|
case int32:
|
||
|
return xValue << rightOperand, xtype
|
||
|
case int64:
|
||
|
return xValue << rightOperand, xtype
|
||
|
case uint:
|
||
|
return xValue << rightOperand, xtype
|
||
|
case uint8:
|
||
|
return xValue << rightOperand, xtype
|
||
|
case uint16:
|
||
|
return xValue << rightOperand, xtype
|
||
|
case uint32:
|
||
|
return xValue << rightOperand, xtype
|
||
|
case uint64:
|
||
|
return xValue << rightOperand, xtype
|
||
|
}
|
||
|
case token.SHR:
|
||
|
switch xValue := x.(type) {
|
||
|
case int:
|
||
|
return xValue >> rightOperand, xtype
|
||
|
case int8:
|
||
|
return xValue >> rightOperand, xtype
|
||
|
case int16:
|
||
|
return xValue >> rightOperand, xtype
|
||
|
case int32:
|
||
|
return xValue >> rightOperand, xtype
|
||
|
case int64:
|
||
|
return xValue >> rightOperand, xtype
|
||
|
case uint:
|
||
|
return xValue >> rightOperand, xtype
|
||
|
case uint8:
|
||
|
return xValue >> rightOperand, xtype
|
||
|
case uint16:
|
||
|
return xValue >> rightOperand, xtype
|
||
|
case uint32:
|
||
|
return xValue >> rightOperand, xtype
|
||
|
case uint64:
|
||
|
return xValue >> rightOperand, xtype
|
||
|
}
|
||
|
}
|
||
|
return nil, nil
|
||
|
}
|
||
|
|
||
|
evalType := xtype
|
||
|
if evalType == nil {
|
||
|
evalType = ytype
|
||
|
}
|
||
|
|
||
|
xValue := reflect.ValueOf(x)
|
||
|
yValue := reflect.ValueOf(y)
|
||
|
if xValue.Kind() == reflect.String && yValue.Kind() == reflect.String {
|
||
|
return xValue.String() + yValue.String(), evalType
|
||
|
}
|
||
|
|
||
|
var targetValue reflect.Value
|
||
|
if xValue.Kind() != reflect.Int {
|
||
|
targetValue = reflect.New(xValue.Type()).Elem()
|
||
|
} else {
|
||
|
targetValue = reflect.New(yValue.Type()).Elem()
|
||
|
}
|
||
|
|
||
|
switch operator {
|
||
|
case token.ADD:
|
||
|
if xValue.CanInt() && yValue.CanInt() {
|
||
|
targetValue.SetInt(xValue.Int() + yValue.Int())
|
||
|
} else if xValue.CanUint() && yValue.CanUint() {
|
||
|
targetValue.SetUint(xValue.Uint() + yValue.Uint())
|
||
|
} else if xValue.CanInt() && yValue.CanUint() {
|
||
|
targetValue.SetUint(uint64(xValue.Int()) + yValue.Uint())
|
||
|
} else if xValue.CanUint() && yValue.CanInt() {
|
||
|
targetValue.SetUint(xValue.Uint() + uint64(yValue.Int()))
|
||
|
}
|
||
|
case token.SUB:
|
||
|
if xValue.CanInt() && yValue.CanInt() {
|
||
|
targetValue.SetInt(xValue.Int() - yValue.Int())
|
||
|
} else if xValue.CanUint() && yValue.CanUint() {
|
||
|
targetValue.SetUint(xValue.Uint() - yValue.Uint())
|
||
|
} else if xValue.CanInt() && yValue.CanUint() {
|
||
|
targetValue.SetUint(uint64(xValue.Int()) - yValue.Uint())
|
||
|
} else if xValue.CanUint() && yValue.CanInt() {
|
||
|
targetValue.SetUint(xValue.Uint() - uint64(yValue.Int()))
|
||
|
}
|
||
|
case token.MUL:
|
||
|
if xValue.CanInt() && yValue.CanInt() {
|
||
|
targetValue.SetInt(xValue.Int() * yValue.Int())
|
||
|
} else if xValue.CanUint() && yValue.CanUint() {
|
||
|
targetValue.SetUint(xValue.Uint() * yValue.Uint())
|
||
|
} else if xValue.CanInt() && yValue.CanUint() {
|
||
|
targetValue.SetUint(uint64(xValue.Int()) * yValue.Uint())
|
||
|
} else if xValue.CanUint() && yValue.CanInt() {
|
||
|
targetValue.SetUint(xValue.Uint() * uint64(yValue.Int()))
|
||
|
}
|
||
|
case token.QUO:
|
||
|
if xValue.CanInt() && yValue.CanInt() {
|
||
|
targetValue.SetInt(xValue.Int() / yValue.Int())
|
||
|
} else if xValue.CanUint() && yValue.CanUint() {
|
||
|
targetValue.SetUint(xValue.Uint() / yValue.Uint())
|
||
|
} else if xValue.CanInt() && yValue.CanUint() {
|
||
|
targetValue.SetUint(uint64(xValue.Int()) / yValue.Uint())
|
||
|
} else if xValue.CanUint() && yValue.CanInt() {
|
||
|
targetValue.SetUint(xValue.Uint() / uint64(yValue.Int()))
|
||
|
}
|
||
|
case token.REM:
|
||
|
if xValue.CanInt() && yValue.CanInt() {
|
||
|
targetValue.SetInt(xValue.Int() % yValue.Int())
|
||
|
} else if xValue.CanUint() && yValue.CanUint() {
|
||
|
targetValue.SetUint(xValue.Uint() % yValue.Uint())
|
||
|
} else if xValue.CanInt() && yValue.CanUint() {
|
||
|
targetValue.SetUint(uint64(xValue.Int()) % yValue.Uint())
|
||
|
} else if xValue.CanUint() && yValue.CanInt() {
|
||
|
targetValue.SetUint(xValue.Uint() % uint64(yValue.Int()))
|
||
|
}
|
||
|
case token.AND:
|
||
|
if xValue.CanInt() && yValue.CanInt() {
|
||
|
targetValue.SetInt(xValue.Int() & yValue.Int())
|
||
|
} else if xValue.CanUint() && yValue.CanUint() {
|
||
|
targetValue.SetUint(xValue.Uint() & yValue.Uint())
|
||
|
} else if xValue.CanInt() && yValue.CanUint() {
|
||
|
targetValue.SetUint(uint64(xValue.Int()) & yValue.Uint())
|
||
|
} else if xValue.CanUint() && yValue.CanInt() {
|
||
|
targetValue.SetUint(xValue.Uint() & uint64(yValue.Int()))
|
||
|
}
|
||
|
case token.OR:
|
||
|
if xValue.CanInt() && yValue.CanInt() {
|
||
|
targetValue.SetInt(xValue.Int() | yValue.Int())
|
||
|
} else if xValue.CanUint() && yValue.CanUint() {
|
||
|
targetValue.SetUint(xValue.Uint() | yValue.Uint())
|
||
|
} else if xValue.CanInt() && yValue.CanUint() {
|
||
|
targetValue.SetUint(uint64(xValue.Int()) | yValue.Uint())
|
||
|
} else if xValue.CanUint() && yValue.CanInt() {
|
||
|
targetValue.SetUint(xValue.Uint() | uint64(yValue.Int()))
|
||
|
}
|
||
|
case token.XOR:
|
||
|
if xValue.CanInt() && yValue.CanInt() {
|
||
|
targetValue.SetInt(xValue.Int() ^ yValue.Int())
|
||
|
} else if xValue.CanUint() && yValue.CanUint() {
|
||
|
targetValue.SetUint(xValue.Uint() ^ yValue.Uint())
|
||
|
} else if xValue.CanInt() && yValue.CanUint() {
|
||
|
targetValue.SetUint(uint64(xValue.Int()) ^ yValue.Uint())
|
||
|
} else if xValue.CanUint() && yValue.CanInt() {
|
||
|
targetValue.SetUint(xValue.Uint() ^ uint64(yValue.Int()))
|
||
|
}
|
||
|
}
|
||
|
return targetValue.Interface(), evalType
|
||
|
}
|