-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathecmascript_methods_test.go
More file actions
99 lines (97 loc) · 3.52 KB
/
Copy pathecmascript_methods_test.go
File metadata and controls
99 lines (97 loc) · 3.52 KB
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
package codegraph
import (
"context"
"strings"
"testing"
)
// +case=`Generator functions and private methods retain concrete kinds, names, full ranges and enclosing owners`
func TestECMAScriptGeneratorAndPrivateDeclarations(t *testing.T) {
for _, path := range []string{"app.js", "app.ts", "app.tsx"} {
t.Run(path, func(t *testing.T) {
methods := []string{
"#hidden() { return 1; }",
"async #pending() { return 1; }",
"*iterate() { yield 1; }",
"async *events() { yield 1; }",
"async() { return 1; }",
"get size() { return 1; }",
"set size(value) {}",
"commented /* name docs */ () {}",
}
names := []string{"#hidden", "#pending", "iterate", "events", "async", "size", "size", "commented"}
if path != "app.js" {
methods = append(methods,
"private async *streamWithRetry(value: string): AsyncGenerator<string> { yield value; }",
"protected async *generic /* type docs */ <T>(value: T): AsyncGenerator<T> { yield value; }",
"public async ordinary<T>(value: T): Promise<T> { return value; }")
names = append(names, "streamWithRetry", "generic", "ordinary")
}
generators := []string{"function* syncItems() { yield 1; }", "async function* asyncItems() { yield 1; }"}
source := "// +spec=Stream values\nexport " + generators[0] + "\nexport " + generators[1] + "\nclass Box {\n" + strings.Join(methods, "\n") + "\n}"
g, report, err := Build(context.Background(), "callables", []Document{{Path: path, Content: []byte(source)}}, Options{})
if err != nil || hasDiagnostic(report, "outline_incomplete") {
t.Fatal(report, err)
}
facts, err := g.Extract(context.Background(), Document{Path: path, Content: []byte(source)})
if err != nil {
t.Fatal(err)
}
expected := map[int]struct {
name, span string
kind NodeKind
}{}
for i, method := range methods {
expected[strings.Index(source, method)] = struct {
name, span string
kind NodeKind
}{names[i], method, Method}
}
for i, generator := range generators {
expected[strings.Index(source, generator)] = struct {
name, span string
kind NodeKind
}{[]string{"syncItems", "asyncItems"}[i], generator, Function}
}
for _, node := range g.Nodes() {
if node.Kind != Method && node.Kind != Function {
continue
}
if node.Location == nil {
t.Fatal(node)
}
want, ok := expected[node.Location.StartByte]
if !ok || node.Name != want.name || node.Kind != want.kind || source[node.Location.StartByte:node.Location.EndByte] != want.span {
t.Fatalf("unexpected callable: %+v, expected %+v", node, want)
}
delete(expected, node.Location.StartByte)
if node.Kind == Method {
edges := g.RelationsTo(node.ID, Contains)
if len(edges) != 1 {
t.Fatal("method owner", node, edges)
}
owner, ok := g.Node(edges[0].Source)
if !ok || owner.Name != "Box" {
t.Fatal("wrong owner", owner)
}
}
if node.Name == "syncItems" && (len(node.Markers) != 1 || node.Markers[0].Text != "Stream values") {
t.Fatal("missing generator marker", node)
}
nameStart := node.Location.StartByte + strings.Index(want.span, want.name)
for _, ref := range facts.References {
if ref.Location.StartByte == nameStart {
t.Fatal("declaration emitted as reference", ref)
}
}
}
if len(expected) != 0 {
t.Fatalf("missing callables: %v", expected)
}
for _, ref := range facts.References {
if ref.Name == "async" {
t.Fatal("modifier emitted as reference", ref)
}
}
})
}
}