~vtuson/scopecreator/twitter-template

« back to all changes in this revision

Viewing changes to src/go/src/code.google.com/p/go.tools/go/loader/source_test.go

  • Committer: Victor Palau
  • Date: 2015-03-11 14:24:42 UTC
  • Revision ID: vtuson@gmail.com-20150311142442-f2pxp111c8ynv232
public release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2013 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
package loader_test
 
6
 
 
7
// This file defines tests of source utilities.
 
8
 
 
9
import (
 
10
        "go/ast"
 
11
        "go/parser"
 
12
        "go/token"
 
13
        "strings"
 
14
        "testing"
 
15
 
 
16
        "code.google.com/p/go.tools/astutil"
 
17
        "code.google.com/p/go.tools/go/loader"
 
18
        "code.google.com/p/go.tools/go/ssa"
 
19
)
 
20
 
 
21
// findInterval parses input and returns the [start, end) positions of
 
22
// the first occurrence of substr in input.  f==nil indicates failure;
 
23
// an error has already been reported in that case.
 
24
//
 
25
func findInterval(t *testing.T, fset *token.FileSet, input, substr string) (f *ast.File, start, end token.Pos) {
 
26
        f, err := parser.ParseFile(fset, "<input>", input, 0)
 
27
        if err != nil {
 
28
                t.Errorf("parse error: %s", err)
 
29
                return
 
30
        }
 
31
 
 
32
        i := strings.Index(input, substr)
 
33
        if i < 0 {
 
34
                t.Errorf("%q is not a substring of input", substr)
 
35
                f = nil
 
36
                return
 
37
        }
 
38
 
 
39
        filePos := fset.File(f.Package)
 
40
        return f, filePos.Pos(i), filePos.Pos(i + len(substr))
 
41
}
 
42
 
 
43
func TestEnclosingFunction(t *testing.T) {
 
44
        tests := []struct {
 
45
                input  string // the input file
 
46
                substr string // first occurrence of this string denotes interval
 
47
                fn     string // name of expected containing function
 
48
        }{
 
49
                // We use distinctive numbers as syntactic landmarks.
 
50
 
 
51
                // Ordinary function:
 
52
                {`package main
 
53
                  func f() { println(1003) }`,
 
54
                        "100", "main.f"},
 
55
                // Methods:
 
56
                {`package main
 
57
                  type T int
 
58
                  func (t T) f() { println(200) }`,
 
59
                        "200", "(main.T).f"},
 
60
                // Function literal:
 
61
                {`package main
 
62
                  func f() { println(func() { print(300) }) }`,
 
63
                        "300", "f$1"},
 
64
                // Doubly nested
 
65
                {`package main
 
66
                  func f() { println(func() { print(func() { print(350) })})}`,
 
67
                        "350", "f$1$1"},
 
68
                // Implicit init for package-level var initializer.
 
69
                {"package main; var a = 400", "400", "main.init"},
 
70
                // No code for constants:
 
71
                {"package main; const a = 500", "500", "(none)"},
 
72
                // Explicit init()
 
73
                {"package main; func init() { println(600) }", "600", "main.init$1"},
 
74
                // Multiple explicit init functions:
 
75
                {`package main
 
76
                  func init() { println("foo") }
 
77
                  func init() { println(800) }`,
 
78
                        "800", "main.init$2"},
 
79
                // init() containing FuncLit.
 
80
                {`package main
 
81
                  func init() { println(func(){print(900)}) }`,
 
82
                        "900", "init$1$1"},
 
83
        }
 
84
        for _, test := range tests {
 
85
                conf := loader.Config{Fset: token.NewFileSet()}
 
86
                f, start, end := findInterval(t, conf.Fset, test.input, test.substr)
 
87
                if f == nil {
 
88
                        continue
 
89
                }
 
90
                path, exact := astutil.PathEnclosingInterval(f, start, end)
 
91
                if !exact {
 
92
                        t.Errorf("EnclosingFunction(%q) not exact", test.substr)
 
93
                        continue
 
94
                }
 
95
 
 
96
                conf.CreateFromFiles("main", f)
 
97
 
 
98
                iprog, err := conf.Load()
 
99
                if err != nil {
 
100
                        t.Error(err)
 
101
                        continue
 
102
                }
 
103
                prog := ssa.Create(iprog, 0)
 
104
                pkg := prog.Package(iprog.Created[0].Pkg)
 
105
                pkg.Build()
 
106
 
 
107
                name := "(none)"
 
108
                fn := ssa.EnclosingFunction(pkg, path)
 
109
                if fn != nil {
 
110
                        name = fn.String()
 
111
                }
 
112
 
 
113
                if name != test.fn {
 
114
                        t.Errorf("EnclosingFunction(%q in %q) got %s, want %s",
 
115
                                test.substr, test.input, name, test.fn)
 
116
                        continue
 
117
                }
 
118
 
 
119
                // While we're here: test HasEnclosingFunction.
 
120
                if has := ssa.HasEnclosingFunction(pkg, path); has != (fn != nil) {
 
121
                        t.Errorf("HasEnclosingFunction(%q in %q) got %v, want %v",
 
122
                                test.substr, test.input, has, fn != nil)
 
123
                        continue
 
124
                }
 
125
        }
 
126
}