fiber/ctx_interface_gen.go

79 lines
1.8 KiB
Go

//go:build ignore
package main
import (
"bufio"
"bytes"
"fmt"
"io"
"os"
"regexp"
"strings"
)
func main() {
const filename = "ctx_interface.go"
// 1) read file
data, err := os.ReadFile(filename)
if err != nil {
panic(fmt.Errorf("failed to read file: %w", err))
}
// 2) patch interface
patched, err := patchCtxFile(data)
if err != nil {
panic(err)
}
// 3) write patched file
if err := os.WriteFile(filename, patched, 0o644); err != nil {
panic(fmt.Errorf("failed to write patched file: %w", err))
}
}
// patchCtxFile adjust the Ctx interface in the given file
func patchCtxFile(input []byte) ([]byte, error) {
// process file line by line
in := bytes.NewReader(input)
scanner := bufio.NewScanner(in)
var outBuf bytes.Buffer
regexCtx := regexp.MustCompile(`(\*Default)Ctx`)
regexApp := regexp.MustCompile(`\*App(\[\w+])?`)
for scanner.Scan() {
line := scanner.Text()
// A) change interface head definition
// => "type Ctx interface {" -> "type Ctx[T any] interface {"
if strings.HasPrefix(line, "type") {
line = strings.Replace(line,
"type CtxGeneric interface {",
"type CtxGeneric[T any] interface {",
1,
)
} else {
// B) replace every use of Ctx with T but only in the function definitions
// via regex and boundary word matching
// => "func (app *App[TCtx]) newCtx() Ctx {" -> "func (app *App[TCtx]) newCtx() T {"
if strings.Contains(line, "Ctx") {
line = regexCtx.ReplaceAllString(line, "T")
}
// C) App with generic type
if strings.Contains(line, "App") {
line = regexApp.ReplaceAllString(line, "*App[T]")
}
}
outBuf.WriteString(line + "\n")
}
if err := scanner.Err(); err != nil && err != io.EOF {
return nil, fmt.Errorf("scanner error: %w", err)
}
return outBuf.Bytes(), nil
}