1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
package gotest
import "strings"
// ParsePackageName returns the package name from file lines, or empty when missing.
func ParsePackageName(lines []string) string {
for _, ln := range lines {
t := strings.TrimSpace(ln)
if !strings.HasPrefix(t, "package ") {
continue
}
name := strings.TrimSpace(strings.TrimPrefix(t, "package "))
if i := strings.Index(name, " "); i >= 0 {
name = name[:i]
}
if i := strings.Index(name, "\t"); i >= 0 {
name = name[:i]
}
if i := strings.Index(name, "//"); i >= 0 {
name = strings.TrimSpace(name[:i])
}
return name
}
return ""
}
// FindFunctionAtLine finds the function enclosing or preceding idx.
// It returns start/end line indexes or -1/-1 when no function is found.
func FindFunctionAtLine(lines []string, idx int) (int, int) {
if len(lines) == 0 {
return -1, -1
}
if idx < 0 {
idx = 0
}
if idx >= len(lines) {
idx = len(lines) - 1
}
start := -1
for i := idx; i >= 0; i-- {
if strings.Contains(lines[i], "func ") {
start = i
break
}
if strings.Contains(lines[i], "}") {
break
}
}
if start == -1 {
return -1, -1
}
depth := 0
seenOpen := false
for i := start; i < len(lines); i++ {
line := lines[i]
for j := 0; j < len(line); j++ {
switch line[j] {
case '{':
depth++
seenOpen = true
case '}':
if depth > 0 {
depth--
}
if seenOpen && depth == 0 {
return start, i
}
}
}
}
if !seenOpen {
return start, start
}
return start, -1
}
// DeriveFuncName extracts function or method name from Go source snippet.
func DeriveFuncName(code string) string {
line := strings.TrimSpace(firstLine(code))
if !strings.HasPrefix(line, "func ") {
return ""
}
rest := strings.TrimSpace(strings.TrimPrefix(line, "func "))
if strings.HasPrefix(rest, "(") {
if i := strings.Index(rest, ")"); i >= 0 && i+1 < len(rest) {
rest = strings.TrimSpace(rest[i+1:])
}
}
if i := strings.Index(rest, "("); i > 0 {
return strings.TrimSpace(rest[:i])
}
return ""
}
// ExportName upper-cases the first character for use in Test* names.
func ExportName(name string) string {
if name == "" {
return ""
}
r := []rune(name)
first := string(r[0])
r[0] = []rune(strings.ToUpper(first))[0]
return string(r)
}
func firstLine(s string) string {
if i := strings.IndexByte(s, '\n'); i >= 0 {
return s[:i]
}
return s
}
|