11package normalizer
22
33import (
4+ "errors"
5+
46 "gopkg.in/bblfsh/sdk.v2/uast"
7+ "gopkg.in/bblfsh/sdk.v2/uast/nodes"
58 "gopkg.in/bblfsh/sdk.v2/uast/role"
69 . "gopkg.in/bblfsh/sdk.v2/uast/transformer"
710)
811
912var Preprocess = Transformers ([][]Transformer {
13+ {Mappings (
14+ // Move the Leading/TrailingTrivia outside of nodes.
15+ //
16+ // This cannot be inside Normalizers because it should precede any
17+ // other transformation.
18+ Map (
19+ opMoveCommentsAnns {Var ("group" )},
20+ Check (Has {uast .KeyType : String (typeGroup )}, Var ("group" )),
21+ ),
22+ )},
1023 {Mappings (Preprocessors ... )},
1124}... )
1225
@@ -37,13 +50,19 @@ func funcDefMap(typ string, async bool) Mapping {
3750 uast .KeyPos : Var ("_pos" ),
3851 uast .KeyType : Var ("_type" ),
3952 },
53+ // Will be filled only if there is a Python3 type annotation
54+ "returns" : Var ("returns" ),
55+ "decorator_list" : Var ("func_decorators" ),
4056 },
4157 Obj {
4258 "Nodes" : Arr (
4359 Obj {
4460 // FIXME: generator=true if it uses yield anywhere in the body
4561 "async" : Bool (async ),
4662 },
63+ Obj {
64+ "decorators" : Var ("func_decorators" ),
65+ },
4766 UASTType (uast.Alias {}, Obj {
4867 // FIXME: can't call identifierWithPos because it would take the position of the
4968 // function node that is not exactly the same as the position of the function name
@@ -53,6 +72,7 @@ func funcDefMap(typ string, async bool) Mapping {
5372 "Node" : UASTType (uast.Function {}, Obj {
5473 "Type" : UASTType (uast.FunctionType {}, Obj {
5574 "Arguments" : Var ("arguments" ),
75+ "Returns" : Var ("returns" ),
5676 }),
5777 "Body" : UASTType (uast.Block {}, Obj {
5878 "Statements" : Var ("body" ),
@@ -89,17 +109,146 @@ func mapStr(nativeType string) Mapping {
89109 {Name : "boxed_value" , Op : UASTType (uast.String {}, Obj {
90110 uast .KeyPos : Var ("pos_" ),
91111 "Value" : Var ("s" ),
92- //"Format": String(""),
93112 })},
94113 {Name : "noops_previous" , Optional : "np_opt" , Op : Var ("noops_previous" )},
95114 {Name : "noops_sameline" , Optional : "ns_opt" , Op : Var ("noops_sameline" )},
96115 }),
97116 )
98117}
99118
119+ var (
120+ typeGroup = uast .TypeOf (uast.Group {})
121+ typeFuncGroup = uast .TypeOf (uast.FunctionGroup {})
122+ )
123+
124+ // Similar (but not equal) to:
125+ // https://github.com/bblfsh/csharp-driver/blob/master/driver/normalizer/normalizer.go#L827
126+ // Should be removed once we have some generic solution in the SDK
127+ type opMoveCommentsAnns struct {
128+ sub Op
129+ }
130+
131+ func (op opMoveCommentsAnns ) Kinds () nodes.Kind {
132+ return nodes .KindObject
133+ }
134+
135+ func (op opMoveCommentsAnns ) Check (st * State , n nodes.Node ) (bool , error ) {
136+ obj , ok := n .(nodes.Object )
137+ if ! ok {
138+ return false , nil
139+ }
140+ modified := false
141+ noops_prevs , ok1 := obj ["noops_previous" ].(nodes.Array )
142+ noops_same , ok2 := obj ["noops_sameline" ].(nodes.Array )
143+ //decorators, ok3 := obj["decorator_list"].(nodes.Array)
144+
145+ if ok1 || ok2 {
146+ // we saved the comments and decorators, remove from them from this node
147+ obj = obj .CloneObject ()
148+ modified = true
149+ delete (obj , "noops_previous" )
150+ delete (obj , "noops_sameline" )
151+ //delete(obj, "decorator_list")
152+ }
153+
154+ if len (noops_prevs ) == 0 || len (noops_same ) == 0 {
155+ if ! modified {
156+ return false , nil
157+ }
158+ return op .sub .Check (st , obj )
159+ }
160+
161+ arr := make (nodes.Array , 0 , len (noops_prevs ) + 1 + len (noops_same ))
162+ arr = append (arr , noops_prevs ... )
163+ arr = append (arr , obj )
164+ arr = append (arr , noops_same )
165+ group , err := uast .ToNode (uast.Group {})
166+ if err != nil {
167+ return false , err
168+ }
169+
170+ obj = group .(nodes.Object )
171+ obj ["Nodes" ] = arr
172+ return op .sub .Check (st , obj )
173+ }
174+
175+ func (op opMoveCommentsAnns ) Construct (st * State , n nodes.Node ) (nodes.Node , error ) {
176+ // TODO(dennwc): implement when we will need a reversal
177+ // see https://github.com/bblfsh/sdk/issues/355
178+ return op .sub .Construct (st , n )
179+ }
180+
181+ // opMergeGroups finds the uast:Group nodes and merges them into a child
182+ // uast:FunctionGroup, if it exists.
183+ //
184+ // This transform is necessary because opMoveTrivias will wrap all nodes that contain trivia
185+ // into a Group node, and the same will happen with MethodDeclaration nodes. But according
186+ // to a UAST schema defined in SDK, the comments (trivia) should be directly inside the
187+ // FunctionGroup node that wraps functions in Semantic mode.
188+ type opMergeGroups struct {
189+ sub Op
190+ }
191+
192+ func (op opMergeGroups ) Kinds () nodes.Kind {
193+ return nodes .KindObject
194+ }
195+
196+
197+ // firstWithType returns an index of the first node type of which matches the filter function.
198+ func firstWithType (arr nodes.Array , fnc func (typ string ) bool ) int {
199+ for i , sub := range arr {
200+ if fnc (uast .TypeOf (sub )) {
201+ return i
202+ }
203+ }
204+ return - 1
205+ }
206+
207+ // Check tests if the current node is uast:Group and if it contains a uast:FunctionGroup
208+ // node, it will remove the current node and merge other children into the FunctionGroup.
209+ func (op opMergeGroups ) Check (st * State , n nodes.Node ) (bool , error ) {
210+ group , ok := n .(nodes.Object )
211+ if ! ok || uast .TypeOf (group ) != typeGroup {
212+ return false , nil
213+ }
214+ arr , ok := group ["Nodes" ].(nodes.Array )
215+ if ! ok {
216+ return false , errors .New ("expected an array in Group.Nodes" )
217+ }
218+ ind := firstWithType (arr , func (typ string ) bool {
219+ return typ == typeFuncGroup
220+ })
221+ if ind < 0 {
222+ return false , nil
223+ }
224+ leading := arr [:ind ]
225+ fgroup := arr [ind ].(nodes.Object )
226+ trailing := arr [ind + 1 :]
227+
228+ arr , ok = fgroup ["Nodes" ].(nodes.Array )
229+ if ! ok {
230+ return false , errors .New ("expected an array in Group.Nodes" )
231+ }
232+ out := make (nodes.Array , 0 , len (leading )+ len (arr )+ len (trailing ))
233+ out = append (out , leading ... )
234+ out = append (out , arr ... )
235+ out = append (out , trailing ... )
236+
237+ fgroup = fgroup .CloneObject ()
238+ fgroup ["Nodes" ] = out
239+
240+ return op .sub .Check (st , fgroup )
241+ }
242+
243+ func (op opMergeGroups ) Construct (st * State , n nodes.Node ) (nodes.Node , error ) {
244+ // TODO(dennwc): implement when we will need a reversal
245+ // see https://github.com/bblfsh/sdk/issues/355
246+ return op .sub .Construct (st , n )
247+ }
248+
100249var Normalizers = []Mapping {
101250
102- // Box Names, Strings, and Bools into a "BoxedFoo" moving the real node to the
251+ // Box Names, Strings, Attributes, ImportFroms and Bools into a "BoxedFoo" moving the real node to the
103252 // "value" property and keeping the comments in the parent (if not, comments would be lost
104253 // when promoting the objects)
105254 Map (
@@ -121,13 +270,10 @@ var Normalizers = []Mapping{
121270 }),
122271 ),
123272
124- // TODO: uncomment after SDK 2.13.x update
125- // (upgrade currently blocked by: https://github.com/bblfsh/sdk/issues/353)
126273 Map (
127274 Part ("_" , Fields {
128275 {Name : uast .KeyType , Op : String ("BoolLiteral" )},
129276 {Name : uast .KeyPos , Op : Var ("pos_" )},
130- //{Name: "LiteralValue", Op: Var("lv")},
131277 {Name : "value" , Op : Var ("lv" )},
132278 {Name : "noops_previous" , Optional : "np_opt" , Op : Var ("noops_previous" )},
133279 {Name : "noops_sameline" , Optional : "ns_opt" , Op : Var ("noops_sameline" )},
@@ -136,13 +282,39 @@ var Normalizers = []Mapping{
136282 {Name : uast .KeyType , Op : String ("BoxedBoolLiteral" )},
137283 {Name : "boxed_value" , Op : UASTType (uast.Bool {}, Obj {
138284 uast .KeyPos : Var ("pos_" ),
285+ << << << < HEAD
286+ "Value" : Var ("lv" ),
287+ || || || | merged common ancestors
288+ "Value" : Var ("lv" ),
289+ == == == =
139290 "Value" : Var ("lv" ),
140291 })},
141292 {Name : "noops_previous" , Optional : "np_opt" , Op : Var ("noops_previous" )},
142293 {Name : "noops_sameline" , Optional : "ns_opt" , Op : Var ("noops_sameline" )},
143294 }),
144295 ),
145296
297+ Map (
298+ Part ("_" , Fields {
299+ {Name : uast .KeyType , Op : String ("Attribute" )},
300+ {Name : uast .KeyPos , Op : Var ("pos_" )},
301+ {Name : "attr" , Op : Var ("aname" )},
302+ {Name : "ctx" , Op : Any ()},
303+ {Name : "noops_previous" , Optional : "np_opt" , Op : Var ("noops_previous" )},
304+ {Name : "noops_sameline" , Optional : "ns_opt" , Op : Var ("noops_sameline" )},
305+ }),
306+ Part ("_" , Fields {
307+ {Name : uast .KeyType , Op : String ("BoxedAttribute" )},
308+ {Name : "boxed_value" , Op : UASTType (uast.Identifier {}, Obj {
309+ uast .KeyPos : Var ("pos_" ),
310+ "Name" : Var ("aname" ),
311+ >> >> >> > Checkpoint with the C # like transform
312+ })},
313+ {Name : "noops_previous" , Optional : "np_opt" , Op : Var ("noops_previous" )},
314+ {Name : "noops_sameline" , Optional : "ns_opt" , Op : Var ("noops_sameline" )},
315+ }),
316+ ),
317+
146318 mapStr ("Bytes" ),
147319 mapStr ("Str" ),
148320 mapStr ("StringLiteral" ),
@@ -174,15 +346,11 @@ var Normalizers = []Mapping{
174346 }),
175347 role .Name ),
176348
177- MapSemantic ("Attribute" , uast.Identifier {}, MapObj (
178- Obj {"attr" : Var ("name" )},
179- Obj {"Name" : Var ("name" )},
180- )),
181-
182349 MapSemantic ("arg" , uast.Argument {}, MapObj (
183350 Obj {
184351 uast .KeyToken : Var ("name" ),
185352 "default" : Var ("init" ),
353+ "ctx" : Any (),
186354 },
187355 Obj {
188356 "Name" : identifierWithPos ("name" ),
@@ -193,6 +361,7 @@ var Normalizers = []Mapping{
193361 MapSemantic ("arg" , uast.Argument {}, MapObj (
194362 Obj {
195363 uast .KeyToken : Var ("name" ),
364+ "ctx" : Any (),
196365 },
197366 Obj {
198367 "Name" : identifierWithPos ("name" ),
@@ -203,6 +372,8 @@ var Normalizers = []Mapping{
203372 Obj {
204373 uast .KeyToken : Var ("name" ),
205374 "default" : Var ("init" ),
375+ // TODO: change this once we've a way to store other nodes on semantic objects
376+ "annotation" : Any (),
206377 },
207378 Obj {
208379 "Init" : Var ("init" ),
@@ -213,6 +384,8 @@ var Normalizers = []Mapping{
213384 MapSemantic ("vararg" , uast.Argument {}, MapObj (
214385 Obj {
215386 uast .KeyToken : Var ("name" ),
387+ // TODO: change this once we've a way to store other nodes on semantic objects
388+ "annotation" : Any (),
216389 },
217390 Obj {
218391 "Name" : identifierWithPos ("name" ),
@@ -223,6 +396,8 @@ var Normalizers = []Mapping{
223396 MapSemantic ("kwarg" , uast.Argument {}, MapObj (
224397 Obj {
225398 uast .KeyToken : Var ("name" ),
399+ // TODO: change this once we've a way to store other nodes on semantic objects
400+ "annotation" : Any (),
226401 },
227402 Obj {
228403 "Name" : identifierWithPos ("name" ),
@@ -317,4 +492,10 @@ var Normalizers = []Mapping{
317492 }),
318493 },
319494 )),
495+
496+ // Merge uast:Group with uast:FunctionGroup.
497+ Map (
498+ opMergeGroups {Var ("group" )},
499+ Check (Has {uast .KeyType : String (uast .TypeOf (uast.FunctionGroup {}))}, Var ("group" )),
500+ ),
320501}
0 commit comments