1// Copyright 2018 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// +build gccgo_examples
6
7package token_test
8
9import (
10	"fmt"
11	"go/ast"
12	"go/parser"
13	"go/token"
14)
15
16func Example_retrievePositionInfo() {
17	fset := token.NewFileSet()
18
19	const src = `package main
20
21import "fmt"
22
23import "go/token"
24
25//line :1:5
26type p = token.Pos
27
28const bad = token.NoPos
29
30//line fake.go:42:11
31func ok(pos p) bool {
32	return pos != bad
33}
34
35/*line :7:9*/func main() {
36	fmt.Println(ok(bad) == bad.IsValid())
37}
38`
39
40	f, err := parser.ParseFile(fset, "main.go", src, 0)
41	if err != nil {
42		fmt.Println(err)
43		return
44	}
45
46	// Print the location and kind of each declaration in f.
47	for _, decl := range f.Decls {
48		// Get the filename, line, and column back via the file set.
49		// We get both the relative and absolute position.
50		// The relative position is relative to the last line directive.
51		// The absolute position is the exact position in the source.
52		pos := decl.Pos()
53		relPosition := fset.Position(pos)
54		absPosition := fset.PositionFor(pos, false)
55
56		// Either a FuncDecl or GenDecl, since we exit on error.
57		kind := "func"
58		if gen, ok := decl.(*ast.GenDecl); ok {
59			kind = gen.Tok.String()
60		}
61
62		// If the relative and absolute positions differ, show both.
63		fmtPosition := relPosition.String()
64		if relPosition != absPosition {
65			fmtPosition += "[" + absPosition.String() + "]"
66		}
67
68		fmt.Printf("%s: %s\n", fmtPosition, kind)
69	}
70
71	//Output:
72	//
73	// main.go:3:1: import
74	// main.go:5:1: import
75	// main.go:1:5[main.go:8:1]: type
76	// main.go:3:1[main.go:10:1]: const
77	// fake.go:42:11[main.go:13:1]: func
78	// fake.go:7:9[main.go:17:14]: func
79}
80