Hallucinate enum support
This commit is contained in:
137
class.go
137
class.go
@@ -16,6 +16,10 @@ import (
|
|||||||
var templatestr string
|
var templatestr string
|
||||||
var classTemplate *template.Template
|
var classTemplate *template.Template
|
||||||
|
|
||||||
|
//go:embed enum.tmpl
|
||||||
|
var enumTemplateStr string
|
||||||
|
var enumTemplate *template.Template
|
||||||
|
|
||||||
var fns = template.FuncMap{
|
var fns = template.FuncMap{
|
||||||
"plus1": func(x int) int {
|
"plus1": func(x int) int {
|
||||||
return x + 1
|
return x + 1
|
||||||
@@ -39,14 +43,19 @@ var fns = template.FuncMap{
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
log := logger.Default.WithPrefix("init")
|
log := logger.Default.WithPrefix("init")
|
||||||
log.Info("Initializing template")
|
log.Info("Initializing templates")
|
||||||
var err error
|
var err error
|
||||||
classTemplate, err = template.New("class").Funcs(fns).Parse(templatestr)
|
classTemplate, err = template.New("class").Funcs(fns).Parse(templatestr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Error parsing template: %v", err)
|
logger.Error("Error parsing class template: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Info("Template initialized successfully")
|
enumTemplate, err = template.New("enum").Funcs(fns).Parse(enumTemplateStr)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Error parsing enum template: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Info("Templates initialized successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -81,6 +90,11 @@ type (
|
|||||||
Params []Param
|
Params []Param
|
||||||
Comment string
|
Comment string
|
||||||
}
|
}
|
||||||
|
Enum struct {
|
||||||
|
Name string
|
||||||
|
Values []string
|
||||||
|
Comment string
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Class) GetOutFile(root string) (*os.File, error) {
|
func (c *Class) GetOutFile(root string) (*os.File, error) {
|
||||||
@@ -115,6 +129,38 @@ func (c *Class) GetOutFile(root string) (*os.File, error) {
|
|||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Enum) GetOutFile(root string) (*os.File, error) {
|
||||||
|
log := logger.Default.WithPrefix("GetOutFile")
|
||||||
|
log.Debug("Getting output file for enum: %s", e.Name)
|
||||||
|
|
||||||
|
if e.Name == "" {
|
||||||
|
log.Error("Name is empty")
|
||||||
|
return nil, fmt.Errorf("Name is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
filename := fmt.Sprintf("%s.lua", e.Name)
|
||||||
|
log.Trace("Original filename: %s", filename)
|
||||||
|
|
||||||
|
filename = strings.ReplaceAll(filename, " ", "")
|
||||||
|
filename = strings.ReplaceAll(filename, "-", "")
|
||||||
|
filename = strings.ReplaceAll(filename, ",", "")
|
||||||
|
filename = strings.ReplaceAll(filename, ":", "")
|
||||||
|
log.Trace("Cleaned filename: %s", filename)
|
||||||
|
|
||||||
|
filePath := filepath.Join(root, filename)
|
||||||
|
filePath = filepath.Clean(filePath)
|
||||||
|
log.Debug("Full file path: %s", filePath)
|
||||||
|
|
||||||
|
f, err := os.Create(filePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error creating file: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Successfully created output file: %s", filePath)
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Class) Write(root string, tmpl *template.Template) error {
|
func (c *Class) Write(root string, tmpl *template.Template) error {
|
||||||
log := logger.Default.WithPrefix("Write")
|
log := logger.Default.WithPrefix("Write")
|
||||||
log.Info("Writing class %s to output", c.ClassName)
|
log.Info("Writing class %s to output", c.ClassName)
|
||||||
@@ -136,6 +182,91 @@ func (c *Class) Write(root string, tmpl *template.Template) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Enum) Write(root string, tmpl *template.Template) error {
|
||||||
|
log := logger.Default.WithPrefix("Write")
|
||||||
|
log.Info("Writing enum %s to output", e.Name)
|
||||||
|
|
||||||
|
outfile, err := e.GetOutFile(root)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error creating output file %v: %v", e.Name, err)
|
||||||
|
return fmt.Errorf("error creating output file %v: %v", e.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("Executing template for enum: %s", e.Name)
|
||||||
|
err = tmpl.Execute(outfile, e)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error writing output file %v: %v", e.Name, err)
|
||||||
|
return fmt.Errorf("error writing output file %v: %v", e.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info("Successfully wrote enum %s to output", e.Name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseEnum(file string) (*Enum, error) {
|
||||||
|
log := logger.Default.WithPrefix(file)
|
||||||
|
log.Info("Starting to parse enum file")
|
||||||
|
|
||||||
|
res := Enum{
|
||||||
|
Values: []string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("Opening file: %s", file)
|
||||||
|
filehandle, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error opening file: %v", err)
|
||||||
|
return nil, fmt.Errorf("error opening file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("Creating goquery document from file")
|
||||||
|
doc, err := goquery.NewDocumentFromReader(filehandle)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error parsing file: %v", err)
|
||||||
|
return nil, fmt.Errorf("error parsing file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find all enum containers
|
||||||
|
codeblocks := doc.Find("div.floatright > div.codecontainer")
|
||||||
|
log.Trace("Found %d code blocks", codeblocks.Length())
|
||||||
|
|
||||||
|
codeblocks.Each(func(i int, s *goquery.Selection) {
|
||||||
|
// Check if this is an enum block
|
||||||
|
enumType := s.Find("span.type").First()
|
||||||
|
if !strings.HasPrefix(strings.TrimSpace(enumType.Text()), "enum") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get enum name from the ID attribute
|
||||||
|
enumName := s.AttrOr("id", "")
|
||||||
|
if enumName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res.Name = enumName
|
||||||
|
|
||||||
|
// Get enum comment if any
|
||||||
|
comment := s.Find("p").Text()
|
||||||
|
if comment != "" {
|
||||||
|
res.Comment = strings.TrimSpace(comment)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get enum values
|
||||||
|
s.Contents().Each(func(i int, s *goquery.Selection) {
|
||||||
|
if s.Is("br") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
text := strings.TrimSpace(s.Text())
|
||||||
|
if text == "" || strings.HasPrefix(text, "enum") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res.Values = append(res.Values, text)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
log.Info("Successfully parsed enum %s with %d values", res.Name, len(res.Values))
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
func ParseClass(file string) (*Class, error) {
|
func ParseClass(file string) (*Class, error) {
|
||||||
log := logger.Default.WithPrefix(file)
|
log := logger.Default.WithPrefix(file)
|
||||||
log.Info("Starting to parse file")
|
log.Info("Starting to parse file")
|
||||||
|
9
enum.tmpl
Normal file
9
enum.tmpl
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
--luacheck: ignore 212 111
|
||||||
|
---@diagnostic disable: missing-return, lowercase-global
|
||||||
|
{{if ne .Comment ""}}-- {{.Comment}}{{end}}
|
||||||
|
---@enum {{.Name}}
|
||||||
|
{{.Name}} = {
|
||||||
|
{{- range $index, $value := .Values}}
|
||||||
|
{{$value}} = "{{$value}}",
|
||||||
|
{{- end}}
|
||||||
|
}
|
82
main.go
82
main.go
@@ -46,6 +46,19 @@ func main() {
|
|||||||
|
|
||||||
// Process each group in parallel
|
// Process each group in parallel
|
||||||
utils.WithWorkers(100, workItems, func(worker int, item WorkItem) {
|
utils.WithWorkers(100, workItems, func(worker int, item WorkItem) {
|
||||||
|
// First check for enums in each file
|
||||||
|
for _, file := range item.GroupFiles {
|
||||||
|
hasEnums, err := processEnums(file, *outdir)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Error processing enums in file %s: %v", file, err)
|
||||||
|
}
|
||||||
|
// If the file only contained enums, skip class parsing
|
||||||
|
if hasEnums && !strings.Contains(file, "[Client]") && !strings.Contains(file, "[Server]") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then process classes
|
||||||
if len(item.GroupFiles) == 1 {
|
if len(item.GroupFiles) == 1 {
|
||||||
// Single file, process normally
|
// Single file, process normally
|
||||||
class, err := ParseClass(item.GroupFiles[0])
|
class, err := ParseClass(item.GroupFiles[0])
|
||||||
@@ -66,6 +79,75 @@ func main() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func processEnums(file string, outdir string) (bool, error) {
|
||||||
|
log := logger.Default.WithPrefix("processEnums")
|
||||||
|
log.Info("Processing enums from file: %s", file)
|
||||||
|
|
||||||
|
filehandle, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("error opening file: %w", err)
|
||||||
|
}
|
||||||
|
defer filehandle.Close()
|
||||||
|
|
||||||
|
doc, err := goquery.NewDocumentFromReader(filehandle)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("error parsing file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find all code containers
|
||||||
|
codeblocks := doc.Find("div.codecontainer")
|
||||||
|
log.Trace("Found %d code blocks", codeblocks.Length())
|
||||||
|
|
||||||
|
foundEnums := false
|
||||||
|
codeblocks.Each(func(i int, s *goquery.Selection) {
|
||||||
|
// Check if this is an enum block
|
||||||
|
enumType := s.Find("span.type").First()
|
||||||
|
if !strings.HasPrefix(strings.TrimSpace(enumType.Text()), "enum") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
foundEnums = true
|
||||||
|
|
||||||
|
// Get enum name from the ID attribute
|
||||||
|
enumName := s.AttrOr("id", "")
|
||||||
|
if enumName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
enum := &Enum{
|
||||||
|
Name: enumName,
|
||||||
|
Values: []string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get enum comment if any
|
||||||
|
comment := s.Find("p").Text()
|
||||||
|
if comment != "" {
|
||||||
|
enum.Comment = strings.TrimSpace(comment)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get enum values
|
||||||
|
s.Contents().Each(func(i int, s *goquery.Selection) {
|
||||||
|
if s.Is("br") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
text := strings.TrimSpace(s.Text())
|
||||||
|
if text == "" || strings.HasPrefix(text, "enum") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
enum.Values = append(enum.Values, text)
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(enum.Values) > 0 {
|
||||||
|
log.Info("Writing enum %s with %d values", enum.Name, len(enum.Values))
|
||||||
|
if err := enum.Write(outdir, enumTemplate); err != nil {
|
||||||
|
log.Error("Error writing enum %s: %v", enum.Name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return foundEnums, nil
|
||||||
|
}
|
||||||
|
|
||||||
func MapType(t string) string {
|
func MapType(t string) string {
|
||||||
// Handle complex types like table<int, string>
|
// Handle complex types like table<int, string>
|
||||||
if strings.Contains(t, "<") && strings.Contains(t, ">") {
|
if strings.Contains(t, "<") && strings.Contains(t, ">") {
|
||||||
|
Reference in New Issue
Block a user