@@ -3,6 +3,7 @@ package swag
33import (
44 "go/ast"
55 "go/token"
6+ "reflect"
67 "strconv"
78)
89
@@ -31,6 +32,7 @@ type PackageDefinitions struct {
3132type ConstVariableGlobalEvaluator interface {
3233 EvaluateConstValue (pkg * PackageDefinitions , cv * ConstVariable , recursiveStack map [string ]struct {}) (interface {}, ast.Expr )
3334 EvaluateConstValueByName (file * ast.File , pkgPath , constVariableName string , recursiveStack map [string ]struct {}) (interface {}, ast.Expr )
35+ FindTypeSpec (typeName string , file * ast.File ) * TypeSpecDef
3436}
3537
3638// NewPackageDefinitions new a PackageDefinitions object
@@ -92,68 +94,89 @@ func (pkg *PackageDefinitions) evaluateConstValue(file *ast.File, iota int, expr
9294 case * ast.BasicLit :
9395 switch valueExpr .Kind {
9496 case token .INT :
95- x , err := strconv .ParseInt (valueExpr .Value , 10 , 64 )
96- if err != nil {
97- return nil , nil
97+ // hexadecimal
98+ if len (valueExpr .Value ) > 2 && valueExpr .Value [0 ] == '0' && valueExpr .Value [1 ] == 'x' {
99+ if x , err := strconv .ParseInt (valueExpr .Value [2 :], 16 , 64 ); err == nil {
100+ return int (x ), nil
101+ } else if x , err := strconv .ParseUint (valueExpr .Value [2 :], 16 , 64 ); err == nil {
102+ return x , nil
103+ } else {
104+ panic (err )
105+ }
106+ }
107+
108+ //octet
109+ if len (valueExpr .Value ) > 1 && valueExpr .Value [0 ] == '0' {
110+ if x , err := strconv .ParseInt (valueExpr .Value [1 :], 8 , 64 ); err == nil {
111+ return int (x ), nil
112+ } else if x , err := strconv .ParseUint (valueExpr .Value [1 :], 8 , 64 ); err == nil {
113+ return x , nil
114+ } else {
115+ panic (err )
116+ }
117+ }
118+
119+ //a basic literal integer is int type in default, or must have an explicit converting type in front
120+ if x , err := strconv .ParseInt (valueExpr .Value , 10 , 64 ); err == nil {
121+ return int (x ), nil
122+ } else if x , err := strconv .ParseUint (valueExpr .Value , 10 , 64 ); err == nil {
123+ return x , nil
124+ } else {
125+ panic (err )
98126 }
99- return int (x ), nil
100- case token .STRING , token .CHAR :
101- return valueExpr .Value [1 : len (valueExpr .Value )- 1 ], nil
127+ case token .STRING :
128+ if valueExpr .Value [0 ] == '`' {
129+ return valueExpr .Value [1 : len (valueExpr .Value )- 1 ], nil
130+ }
131+ return EvaluateEscapedString (valueExpr .Value [1 : len (valueExpr .Value )- 1 ]), nil
132+ case token .CHAR :
133+ return EvaluateEscapedChar (valueExpr .Value [1 : len (valueExpr .Value )- 1 ]), nil
102134 }
103135 case * ast.UnaryExpr :
104136 x , evalType := pkg .evaluateConstValue (file , iota , valueExpr .X , globalEvaluator , recursiveStack )
105137 if x == nil {
106- return nil , nil
107- }
108- switch valueExpr .Op {
109- case token .SUB :
110- return - x .(int ), evalType
111- case token .XOR :
112- return ^ (x .(int )), evalType
138+ return x , evalType
113139 }
140+ return EvaluateUnary (x , valueExpr .Op , evalType )
114141 case * ast.BinaryExpr :
115142 x , evalTypex := pkg .evaluateConstValue (file , iota , valueExpr .X , globalEvaluator , recursiveStack )
116143 y , evalTypey := pkg .evaluateConstValue (file , iota , valueExpr .Y , globalEvaluator , recursiveStack )
117144 if x == nil || y == nil {
118145 return nil , nil
119146 }
120- evalType := evalTypex
121- if evalType == nil {
122- evalType = evalTypey
123- }
124- switch valueExpr .Op {
125- case token .ADD :
126- if ix , ok := x .(int ); ok {
127- return ix + y .(int ), evalType
128- } else if sx , ok := x .(string ); ok {
129- return sx + y .(string ), evalType
130- }
131- case token .SUB :
132- return x .(int ) - y .(int ), evalType
133- case token .MUL :
134- return x .(int ) * y .(int ), evalType
135- case token .QUO :
136- return x .(int ) / y .(int ), evalType
137- case token .REM :
138- return x .(int ) % y .(int ), evalType
139- case token .AND :
140- return x .(int ) & y .(int ), evalType
141- case token .OR :
142- return x .(int ) | y .(int ), evalType
143- case token .XOR :
144- return x .(int ) ^ y .(int ), evalType
145- case token .SHL :
146- return x .(int ) << y .(int ), evalType
147- case token .SHR :
148- return x .(int ) >> y .(int ), evalType
149- }
147+ return EvaluateBinary (x , y , valueExpr .Op , evalTypex , evalTypey )
150148 case * ast.ParenExpr :
151149 return pkg .evaluateConstValue (file , iota , valueExpr .X , globalEvaluator , recursiveStack )
152150 case * ast.CallExpr :
153151 //data conversion
154- if ident , ok := valueExpr .Fun .(* ast.Ident ); ok && len (valueExpr .Args ) == 1 && IsGolangPrimitiveType (ident .Name ) {
155- arg , _ := pkg .evaluateConstValue (file , iota , valueExpr .Args [0 ], globalEvaluator , recursiveStack )
156- return arg , nil
152+ if len (valueExpr .Args ) != 1 {
153+ return nil , nil
154+ }
155+ arg := valueExpr .Args [0 ]
156+ if ident , ok := valueExpr .Fun .(* ast.Ident ); ok {
157+ name := ident .Name
158+ if name == "uintptr" {
159+ name = "uint"
160+ }
161+ if IsGolangPrimitiveType (name ) {
162+ value , _ := pkg .evaluateConstValue (file , iota , arg , globalEvaluator , recursiveStack )
163+ value = EvaluateDataConversion (value , name )
164+ return value , nil
165+ } else if name == "len" {
166+ value , _ := pkg .evaluateConstValue (file , iota , arg , globalEvaluator , recursiveStack )
167+ return reflect .ValueOf (value ).Len (), nil
168+ }
169+ typeDef := globalEvaluator .FindTypeSpec (name , file )
170+ if typeDef == nil {
171+ return nil , nil
172+ }
173+ return arg , valueExpr .Fun
174+ } else if selector , ok := valueExpr .Fun .(* ast.SelectorExpr ); ok {
175+ typeDef := globalEvaluator .FindTypeSpec (fullTypeName (selector .X .(* ast.Ident ).Name , selector .Sel .Name ), file )
176+ if typeDef == nil {
177+ return nil , nil
178+ }
179+ return arg , typeDef .TypeSpec .Type
157180 }
158181 }
159182 return nil , nil
0 commit comments