File: package_generator.go

package info (click to toggle)
golang-github-pocketbase-tygoja 0.0~git20250812.97ffe05-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,164 kB
  • sloc: javascript: 5; makefile: 4
file content (104 lines) | stat: -rw-r--r-- 2,487 bytes parent folder | download
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
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
	withPkgDoc bool

	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")

	if g.withPkgDoc {
		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
}