mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-04 23:23:48 +08:00

* Rename predicates source file * Overhaul and document type predicates * Fix model collection logic for named types * Fix map key type rendering * Fix map creation code * Fix rendering of structs that implement marshaler interfaces * Fix type cycle detection to take type args into account * Fix enum and typeparam field initialisation * Improve unsupported type warnings * Remove internal models file * Deduplicate template code * Accept generic aliases in static analyser * Support new `encoding/json` flag `omitzero` * Handle special cases when rendering generic aliases * Update npm test dependencies * Test class aliases and implicit private dependencies * Test marshaler combinations * Test map key types * Remove bad map keys from unrelated tests * Test service discovery through generic aliases * Test generic aliases * Test warning messages * Disable go1.24 tests * Update changelog * Restore rendering of injected lines in index file * Test directives * Add wails:ignore directive * Fix typo * Move injections to the bottom of service files * Handle errors from closing files * Do not emit messages when services define only lifecycle methods * Add internal directive for services and models * Update changelog * Fix error in service templates * Test internal directive on services/models * Fix error in index template * Base testdata updates * Testdata for class aliases and implicit private dependencies * Testdata for marshaler combinations * Testdata for map key types * Testdata for bad map key fixes * Add weakly typed enums aka alias constants * Testdata for enum and typeparam field fixes * Testdata for generic aliases * Testdata for warning messages * Testdata for directives * Testdata for weakly typed enums * Update binding example * Update services example * Remove go1.24 testdata * Update cli doc * Fix analyser tests * Fix windows tests... hopefully * go mod tidy on examples * Update bindings guide --------- Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
142 lines
3.8 KiB
Go
142 lines
3.8 KiB
Go
package render
|
|
|
|
import (
|
|
"go/types"
|
|
"io"
|
|
"slices"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"github.com/wailsapp/wails/v3/internal/flags"
|
|
"github.com/wailsapp/wails/v3/internal/generator/collect"
|
|
)
|
|
|
|
// Renderer holds the template set for a given configuration.
|
|
// It provides methods for rendering various output modules.
|
|
type Renderer struct {
|
|
options *flags.GenerateBindingsOptions
|
|
collector *collect.Collector
|
|
|
|
ext string
|
|
|
|
service *template.Template
|
|
typedefs *template.Template
|
|
}
|
|
|
|
// NewRenderer initialises a code renderer
|
|
// for the given configuration and data collector.
|
|
func NewRenderer(options *flags.GenerateBindingsOptions, collector *collect.Collector) *Renderer {
|
|
ext := ".js"
|
|
if options.TS {
|
|
ext = ".ts"
|
|
}
|
|
|
|
return &Renderer{
|
|
options: options,
|
|
collector: collector,
|
|
|
|
ext: ext,
|
|
|
|
service: tmplService[tmplLanguage(options.TS)],
|
|
typedefs: tmplModels[tmplLanguage(options.TS)],
|
|
}
|
|
}
|
|
|
|
// ServiceFile returns the standard name of a service file
|
|
// for the given struct name, with the appropriate extension.
|
|
func (renderer *Renderer) ServiceFile(name string) string {
|
|
return strings.ToLower(name) + renderer.ext
|
|
}
|
|
|
|
// ModelsFile returns the standard name of a models file
|
|
// with the appropriate extension.
|
|
func (renderer *Renderer) ModelsFile() string {
|
|
return renderer.options.ModelsFilename + renderer.ext
|
|
}
|
|
|
|
// IndexFile returns the standard name of a package index file
|
|
// with the appropriate extension.
|
|
func (renderer *Renderer) IndexFile() string {
|
|
return renderer.options.IndexFilename + renderer.ext
|
|
}
|
|
|
|
// Service renders binding code for the given service type to w.
|
|
func (renderer *Renderer) Service(w io.Writer, info *collect.ServiceInfo) error {
|
|
return renderer.service.Execute(w, &struct {
|
|
module
|
|
Service *collect.ServiceInfo
|
|
}{
|
|
module{
|
|
Renderer: renderer,
|
|
GenerateBindingsOptions: renderer.options,
|
|
Imports: info.Imports,
|
|
},
|
|
info,
|
|
})
|
|
}
|
|
|
|
// Typedefs renders type definitions for the given list of models.
|
|
func (renderer *Renderer) Models(w io.Writer, imports *collect.ImportMap, models []*collect.ModelInfo) error {
|
|
if !renderer.options.UseInterfaces {
|
|
// Sort class aliases after the class they alias.
|
|
// Works in amortized linear time thanks to an auxiliary map.
|
|
|
|
// Track postponed class aliases and their dependencies.
|
|
aliases := make(map[types.Object][]*collect.ModelInfo, len(models))
|
|
|
|
models = slices.Clone(models)
|
|
for i, j := 0, 0; i < len(models); i++ {
|
|
if models[i].Type != nil && models[i].Predicates.IsClass {
|
|
// models[i] is a class alias:
|
|
// models[i].Type is guaranteed to be
|
|
// either an alias or a named type
|
|
obj := models[i].Type.(interface{ Obj() *types.TypeName }).Obj()
|
|
if obj.Pkg().Path() == imports.Self {
|
|
// models[i] aliases a type from the current module.
|
|
if a, ok := aliases[obj]; !ok || len(a) > 0 {
|
|
// The aliased type has not been visited already, postpone.
|
|
aliases[obj] = append(a, models[i])
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
// Append models[i].
|
|
models[j] = models[i]
|
|
j++
|
|
|
|
// Keep appending aliases whose aliased type has been just appended.
|
|
for k := j - 1; k < j; k++ {
|
|
a := aliases[models[k].Object()]
|
|
aliases[models[k].Object()] = nil // Mark aliased model as visited
|
|
j += copy(models[j:], a)
|
|
}
|
|
}
|
|
}
|
|
|
|
return renderer.typedefs.Execute(w, &struct {
|
|
module
|
|
Models []*collect.ModelInfo
|
|
}{
|
|
module{
|
|
Renderer: renderer,
|
|
GenerateBindingsOptions: renderer.options,
|
|
Imports: imports,
|
|
},
|
|
models,
|
|
})
|
|
}
|
|
|
|
// Index renders the given package index to w.
|
|
func (renderer *Renderer) Index(w io.Writer, index *collect.PackageIndex) error {
|
|
return tmplIndex.Execute(w, &struct {
|
|
*collect.PackageIndex
|
|
*Renderer
|
|
*flags.GenerateBindingsOptions
|
|
}{
|
|
index,
|
|
renderer,
|
|
renderer.options,
|
|
})
|
|
}
|