1// Copyright 2020 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// This file implements helper functions for scope position computations. 6 7package syntax 8 9// StartPos returns the start position of n. 10func StartPos(n Node) Pos { 11 // Cases for nodes which don't need a correction are commented out. 12 for m := n; ; { 13 switch n := m.(type) { 14 case nil: 15 panic("nil node") 16 17 // packages 18 case *File: 19 // file block starts at the beginning of the file 20 return MakePos(n.Pos().Base(), 1, 1) 21 22 // declarations 23 // case *ImportDecl: 24 // case *ConstDecl: 25 // case *TypeDecl: 26 // case *VarDecl: 27 // case *FuncDecl: 28 29 // expressions 30 // case *BadExpr: 31 // case *Name: 32 // case *BasicLit: 33 case *CompositeLit: 34 if n.Type != nil { 35 m = n.Type 36 continue 37 } 38 return n.Pos() 39 case *KeyValueExpr: 40 m = n.Key 41 // case *FuncLit: 42 // case *ParenExpr: 43 case *SelectorExpr: 44 m = n.X 45 case *IndexExpr: 46 m = n.X 47 // case *SliceExpr: 48 case *AssertExpr: 49 m = n.X 50 case *TypeSwitchGuard: 51 if n.Lhs != nil { 52 m = n.Lhs 53 continue 54 } 55 m = n.X 56 case *Operation: 57 if n.Y != nil { 58 m = n.X 59 continue 60 } 61 return n.Pos() 62 case *CallExpr: 63 m = n.Fun 64 case *ListExpr: 65 if len(n.ElemList) > 0 { 66 m = n.ElemList[0] 67 continue 68 } 69 return n.Pos() 70 // types 71 // case *ArrayType: 72 // case *SliceType: 73 // case *DotsType: 74 // case *StructType: 75 // case *Field: 76 // case *InterfaceType: 77 // case *FuncType: 78 // case *MapType: 79 // case *ChanType: 80 81 // statements 82 // case *EmptyStmt: 83 // case *LabeledStmt: 84 // case *BlockStmt: 85 // case *ExprStmt: 86 case *SendStmt: 87 m = n.Chan 88 // case *DeclStmt: 89 case *AssignStmt: 90 m = n.Lhs 91 // case *BranchStmt: 92 // case *CallStmt: 93 // case *ReturnStmt: 94 // case *IfStmt: 95 // case *ForStmt: 96 // case *SwitchStmt: 97 // case *SelectStmt: 98 99 // helper nodes 100 case *RangeClause: 101 if n.Lhs != nil { 102 m = n.Lhs 103 continue 104 } 105 m = n.X 106 // case *CaseClause: 107 // case *CommClause: 108 109 default: 110 return n.Pos() 111 } 112 } 113} 114 115// EndPos returns the approximate end position of n in the source. 116// For some nodes (*Name, *BasicLit) it returns the position immediately 117// following the node; for others (*BlockStmt, *SwitchStmt, etc.) it 118// returns the position of the closing '}'; and for some (*ParenExpr) 119// the returned position is the end position of the last enclosed 120// expression. 121// Thus, EndPos should not be used for exact demarcation of the 122// end of a node in the source; it is mostly useful to determine 123// scope ranges where there is some leeway. 124func EndPos(n Node) Pos { 125 for m := n; ; { 126 switch n := m.(type) { 127 case nil: 128 panic("nil node") 129 130 // packages 131 case *File: 132 return n.EOF 133 134 // declarations 135 case *ImportDecl: 136 m = n.Path 137 case *ConstDecl: 138 if n.Values != nil { 139 m = n.Values 140 continue 141 } 142 if n.Type != nil { 143 m = n.Type 144 continue 145 } 146 if l := len(n.NameList); l > 0 { 147 m = n.NameList[l-1] 148 continue 149 } 150 return n.Pos() 151 case *TypeDecl: 152 m = n.Type 153 case *VarDecl: 154 if n.Values != nil { 155 m = n.Values 156 continue 157 } 158 if n.Type != nil { 159 m = n.Type 160 continue 161 } 162 if l := len(n.NameList); l > 0 { 163 m = n.NameList[l-1] 164 continue 165 } 166 return n.Pos() 167 case *FuncDecl: 168 if n.Body != nil { 169 m = n.Body 170 continue 171 } 172 m = n.Type 173 174 // expressions 175 case *BadExpr: 176 return n.Pos() 177 case *Name: 178 p := n.Pos() 179 return MakePos(p.Base(), p.Line(), p.Col()+uint(len(n.Value))) 180 case *BasicLit: 181 p := n.Pos() 182 return MakePos(p.Base(), p.Line(), p.Col()+uint(len(n.Value))) 183 case *CompositeLit: 184 return n.Rbrace 185 case *KeyValueExpr: 186 m = n.Value 187 case *FuncLit: 188 m = n.Body 189 case *ParenExpr: 190 m = n.X 191 case *SelectorExpr: 192 m = n.Sel 193 case *IndexExpr: 194 m = n.Index 195 case *SliceExpr: 196 for i := len(n.Index) - 1; i >= 0; i-- { 197 if x := n.Index[i]; x != nil { 198 m = x 199 continue 200 } 201 } 202 m = n.X 203 case *AssertExpr: 204 m = n.Type 205 case *TypeSwitchGuard: 206 m = n.X 207 case *Operation: 208 if n.Y != nil { 209 m = n.Y 210 continue 211 } 212 m = n.X 213 case *CallExpr: 214 if l := lastExpr(n.ArgList); l != nil { 215 m = l 216 continue 217 } 218 m = n.Fun 219 case *ListExpr: 220 if l := lastExpr(n.ElemList); l != nil { 221 m = l 222 continue 223 } 224 return n.Pos() 225 226 // types 227 case *ArrayType: 228 m = n.Elem 229 case *SliceType: 230 m = n.Elem 231 case *DotsType: 232 m = n.Elem 233 case *StructType: 234 if l := lastField(n.FieldList); l != nil { 235 m = l 236 continue 237 } 238 return n.Pos() 239 // TODO(gri) need to take TagList into account 240 case *Field: 241 if n.Type != nil { 242 m = n.Type 243 continue 244 } 245 m = n.Name 246 case *InterfaceType: 247 if l := lastField(n.MethodList); l != nil { 248 m = l 249 continue 250 } 251 return n.Pos() 252 case *FuncType: 253 if l := lastField(n.ResultList); l != nil { 254 m = l 255 continue 256 } 257 if l := lastField(n.ParamList); l != nil { 258 m = l 259 continue 260 } 261 return n.Pos() 262 case *MapType: 263 m = n.Value 264 case *ChanType: 265 m = n.Elem 266 267 // statements 268 case *EmptyStmt: 269 return n.Pos() 270 case *LabeledStmt: 271 m = n.Stmt 272 case *BlockStmt: 273 return n.Rbrace 274 case *ExprStmt: 275 m = n.X 276 case *SendStmt: 277 m = n.Value 278 case *DeclStmt: 279 if l := lastDecl(n.DeclList); l != nil { 280 m = l 281 continue 282 } 283 return n.Pos() 284 case *AssignStmt: 285 m = n.Rhs 286 if m == nil { 287 p := EndPos(n.Lhs) 288 return MakePos(p.Base(), p.Line(), p.Col()+2) 289 } 290 case *BranchStmt: 291 if n.Label != nil { 292 m = n.Label 293 continue 294 } 295 return n.Pos() 296 case *CallStmt: 297 m = n.Call 298 case *ReturnStmt: 299 if n.Results != nil { 300 m = n.Results 301 continue 302 } 303 return n.Pos() 304 case *IfStmt: 305 if n.Else != nil { 306 m = n.Else 307 continue 308 } 309 m = n.Then 310 case *ForStmt: 311 m = n.Body 312 case *SwitchStmt: 313 return n.Rbrace 314 case *SelectStmt: 315 return n.Rbrace 316 317 // helper nodes 318 case *RangeClause: 319 m = n.X 320 case *CaseClause: 321 if l := lastStmt(n.Body); l != nil { 322 m = l 323 continue 324 } 325 return n.Colon 326 case *CommClause: 327 if l := lastStmt(n.Body); l != nil { 328 m = l 329 continue 330 } 331 return n.Colon 332 333 default: 334 return n.Pos() 335 } 336 } 337} 338 339func lastDecl(list []Decl) Decl { 340 if l := len(list); l > 0 { 341 return list[l-1] 342 } 343 return nil 344} 345 346func lastExpr(list []Expr) Expr { 347 if l := len(list); l > 0 { 348 return list[l-1] 349 } 350 return nil 351} 352 353func lastStmt(list []Stmt) Stmt { 354 if l := len(list); l > 0 { 355 return list[l-1] 356 } 357 return nil 358} 359 360func lastField(list []*Field) *Field { 361 if l := len(list); l > 0 { 362 return list[l-1] 363 } 364 return nil 365} 366