5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 23:51:44 +08:00
wails/v2/internal/binding/reflect.go
Oleg Gulevskyy ca8a1fab36
Ability to define prefix / suffix for TS module (#2101)
* add tspostfix and tsprefix flags + organise under struct

* postifx -> suffix

* tsPrefix options on bindings struct

* pass prefix and suffix to the executable

* add support for CLI flags for generating module

* method to set TSpref/suff to bindings

* use passed ts prefix for typescriptify

* add brief Readme udpate to include new flags

* create reusable common flags

* use common flags instead of hardcoded text

* support tsprefix & suffix for dev

* add tsPrefix & tsSuffix for build cmd

* take pref & suff in account when gen d.ts

* export colorsful log functions into utils for reuse

* detect and warn the user about usage of reserved keyword

* fmt

* add TrimSpace on fn input

* refactor utils -> logutils

* add bindings -> ts_generation options to wailsjson parse

* use wailsjson for ts generation

* update warning message + extract to func

* remove suff/pref info from readme

* update json schema

* add tests for prefix and suffix case

* rename suffix method

* Update v2/internal/typescriptify/typescriptify.go

Co-authored-by: Lea Anthony <lea.anthony@gmail.com>

* Update website/static/schemas/config.v2.json

Co-authored-by: Lea Anthony <lea.anthony@gmail.com>

* Update website/static/schemas/config.v2.json

Co-authored-by: Lea Anthony <lea.anthony@gmail.com>

* update changelog

* Minor tweaks

Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
2022-11-24 21:33:58 +11:00

179 lines
4.7 KiB
Go
Executable File

package binding
import (
"fmt"
"reflect"
"runtime"
"strings"
)
// isStructPtr returns true if the value given is a
// pointer to a struct
func isStructPtr(value interface{}) bool {
return reflect.ValueOf(value).Kind() == reflect.Ptr &&
reflect.ValueOf(value).Elem().Kind() == reflect.Struct
}
// isFunction returns true if the given value is a function
func isFunction(value interface{}) bool {
return reflect.ValueOf(value).Kind() == reflect.Func
}
// isStructPtr returns true if the value given is a struct
func isStruct(value interface{}) bool {
return reflect.ValueOf(value).Kind() == reflect.Struct
}
func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) {
// Create result placeholder
var result []*BoundMethod
// Check type
if !isStructPtr(value) {
if isStruct(value) {
name := reflect.ValueOf(value).Type().Name()
return nil, fmt.Errorf("%s is a struct, not a pointer to a struct", name)
}
if isFunction(value) {
name := runtime.FuncForPC(reflect.ValueOf(value).Pointer()).Name()
return nil, fmt.Errorf("%s is a function, not a pointer to a struct. Wails v2 has deprecated the binding of functions. Please wrap your functions up in a struct and bind a pointer to that struct.", name)
}
return nil, fmt.Errorf("not a pointer to a struct.")
}
// Process Struct
structType := reflect.TypeOf(value)
structValue := reflect.ValueOf(value)
structTypeString := structType.String()
baseName := structTypeString[1:]
// Process Methods
for i := 0; i < structType.NumMethod(); i++ {
methodDef := structType.Method(i)
methodName := methodDef.Name
fullMethodName := baseName + "." + methodName
method := structValue.MethodByName(methodName)
methodReflectName := runtime.FuncForPC(methodDef.Func.Pointer()).Name()
if b.exemptions.Contains(methodReflectName) {
continue
}
// Create new method
boundMethod := &BoundMethod{
Name: fullMethodName,
Inputs: nil,
Outputs: nil,
Comments: "",
Method: method,
}
// Iterate inputs
methodType := method.Type()
inputParamCount := methodType.NumIn()
var inputs []*Parameter
for inputIndex := 0; inputIndex < inputParamCount; inputIndex++ {
input := methodType.In(inputIndex)
thisParam := newParameter("", input)
thisInput := input
if thisInput.Kind() == reflect.Slice {
thisInput = thisInput.Elem()
}
// Process struct pointer params
if thisInput.Kind() == reflect.Ptr {
if thisInput.Elem().Kind() == reflect.Struct {
typ := thisInput.Elem()
a := reflect.New(typ)
s := reflect.Indirect(a).Interface()
name := typ.Name()
packageName := getPackageName(thisInput.String())
b.AddStructToGenerateTS(packageName, name, s)
}
}
// Process struct params
if thisInput.Kind() == reflect.Struct {
a := reflect.New(thisInput)
s := reflect.Indirect(a).Interface()
name := thisInput.Name()
packageName := getPackageName(thisInput.String())
b.AddStructToGenerateTS(packageName, name, s)
}
inputs = append(inputs, thisParam)
}
boundMethod.Inputs = inputs
// Iterate outputs
// TODO: Determine what to do about limiting return types
// especially around errors.
outputParamCount := methodType.NumOut()
var outputs []*Parameter
for outputIndex := 0; outputIndex < outputParamCount; outputIndex++ {
output := methodType.Out(outputIndex)
thisParam := newParameter("", output)
thisOutput := output
if thisOutput.Kind() == reflect.Slice {
thisOutput = thisOutput.Elem()
}
// Process struct pointer params
if thisOutput.Kind() == reflect.Ptr {
if thisOutput.Elem().Kind() == reflect.Struct {
typ := thisOutput.Elem()
a := reflect.New(typ)
s := reflect.Indirect(a).Interface()
name := typ.Name()
packageName := getPackageName(thisOutput.String())
b.AddStructToGenerateTS(packageName, name, s)
}
}
// Process struct params
if thisOutput.Kind() == reflect.Struct {
a := reflect.New(thisOutput)
s := reflect.Indirect(a).Interface()
name := thisOutput.Name()
packageName := getPackageName(thisOutput.String())
b.AddStructToGenerateTS(packageName, name, s)
}
outputs = append(outputs, thisParam)
}
boundMethod.Outputs = outputs
// Save method in result
result = append(result, boundMethod)
}
return result, nil
}
func getPackageName(in string) string {
result := strings.Split(in, ".")[0]
result = strings.ReplaceAll(result, "[]", "")
result = strings.ReplaceAll(result, "*", "")
return result
}
func getSplitReturn(in string) (string, string) {
result := strings.Split(in, ".")
return result[0], result[1]
}
func hasElements(typ reflect.Type) bool {
kind := typ.Kind()
return kind == reflect.Ptr || kind == reflect.Array || kind == reflect.Slice || kind == reflect.Map
}