forked from pocketbase/tygoja
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpackage_generator.go
99 lines (80 loc) · 2.37 KB
/
package_generator.go
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 tygoja
import (
"go/ast"
"go/token"
"strings"
"golang.org/x/tools/go/packages"
)
// PackageGenerator is responsible for generating the code for a single input package.
type PackageGenerator struct {
conf *Config
pkg *packages.Package
types []string
generatedTypes map[string]struct{}
unknownTypes map[string]struct{}
imports map[string][]string // path -> []names/aliases
}
// Generate generates the typings for a single package.
func (g *PackageGenerator) Generate() (string, error) {
s := new(strings.Builder)
namespace := packageNameFromPath(g.pkg.ID)
s.WriteString("\n")
for _, f := range g.pkg.Syntax {
if f.Doc == nil || len(f.Doc.List) == 0 {
continue
}
g.writeCommentGroup(s, f.Doc, 0)
}
g.writeStartModifier(s, 0)
s.WriteString("namespace ")
s.WriteString(namespace)
s.WriteString(" {\n")
// register the aliased imports within the package namespace
// (see https://www.typescriptlang.org/docs/handbook/namespaces.html#aliases)
loadedAliases := map[string]struct{}{}
for _, file := range g.pkg.Syntax {
for _, imp := range file.Imports {
path := strings.Trim(imp.Path.Value, `"' `)
pgkName := packageNameFromPath(path)
alias := pgkName
if imp.Name != nil && imp.Name.Name != "" && imp.Name.Name != "_" {
alias = imp.Name.Name
if _, ok := loadedAliases[alias]; ok {
continue // already registered
}
loadedAliases[alias] = struct{}{}
g.writeIndent(s, 1)
s.WriteString("// @ts-ignore\n")
g.writeIndent(s, 1)
s.WriteString("import ")
s.WriteString(alias)
s.WriteString(" = ")
s.WriteString(pgkName)
s.WriteString("\n")
}
// register the import to export its package later
if !exists(g.imports[path], alias) {
if g.imports[path] == nil {
g.imports[path] = []string{}
}
g.imports[path] = append(g.imports[path], alias)
}
}
ast.Inspect(file, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.FuncDecl: // FuncDecl can be package level function or struct method
g.writeFuncDecl(s, x, 1)
return false
case *ast.GenDecl: // GenDecl can be an import, type, var, or const expression
if x.Tok == token.VAR || x.Tok == token.IMPORT {
return false // ignore variables and import statements for now
}
g.writeGroupDecl(s, x, 1)
return false
}
return true
})
}
s.WriteString("}\n")
return s.String(), nil
}