2022-09-14 09:15:09 -05:00
package codegen
import (
"bytes"
"fmt"
Reconcile coremodels, entities, objects under new kind framework (#56492)
* Update thema to latest
* Deal with s/Library/*Runtime/
* Commit new, working results of codegen
* We like pointers now
* Always take runtime arg for NewBase()
* Sketchy handwavy pass at entity meta framework
* Little nibbles
* Update pkg/framework/coremodel/entityframework.cue
Co-authored-by: Artur Wierzbicki <wierzbicki.artur.94@gmail.com>
* Move file into new framework location
* Introduce loaders, Go code
* Complete rename to kind
* Flesh out framework, add svg/dashboard examples
* Cruft removal
* Remove generated kind go files from gitignore
* Refine maturity concept, add SlotKind
* Update embed and go deps
* Export PrefixWithGrafanaCUE
* Make the loader actually work, holy crap
* Many small tweaks to type.cue
* Add Apache 2 licensing exceptions for kinds
* Add new kinds dir, start of generator
* Roll back to earlier oapi-codegen
* Introduce new grafana-specific CUE loaders
* Introduce new tidy code generators framework
* Catch up kind framework with tinkering
* Add slices for the generators
* Add write/verify step to main generator
* Many renames
* Split up kind framework cue files
* Use kind.Decl within generated kinds
* Create kind.SomeDecl wrapper type to cache lineages
* Better names again
* Get one generated implemented, hopefully
* Copy dashboard schema into new kind.cue
* Small fixes to make the initial gen work
* Put svg kind in its new home
* Add generated Go dashboard type
* More renames and cleanups
* Add base kind registry and generator
* Stop blacklisting *_gen.go files
This is not the Go best practice, anyway. All we actually want to ignore
for enterprise is generated wire files.
* Change codegen output directories
pkg/kind -> pkg/kinds
pkg/registry/kindreg -> pkg/registry/corekind
* Rename pkg/framework/kind to pkg/kindsys
* Add core structured kind generator
* Add plural and machine names to kind spec
* Copy playlist over to kind system
* Consolidate kindsys files
* Add raw kind generator
* Update CODEOWNERS for kind framework
* Touch up comments a bit
* More docs tweaks
* Remove generated types to reduce noise for review
* Split each generator into its own file
* Rename Slot kind to Composable kind
* Add handwavy types for customkind loading
* Guard against init calls to framework loader
* First pass at doc on extending the kind system
* Improve attribute example in docs
* Fix wire imports
* Add basic TS types generator
* Fix composable kind category def
* No need for a separate file with generate directive
* Catch dashboard schema up
* Rename generator types to something saner and generic
* Make version configurable in ts/go generators
* Add CommonMeta to ease property access
* Add kindsys prop indicating whether lineage is group
* Put all kind categories back in a single file
* Finish with kindsys group props
* Refactor maturity progression per discussion
- Replace "committed" with "merged"
- All kindcats can use all maturity levels, at least for now
* Convert ts veneer index generator to modular system
* Move over to new jennywrites framework
* Strip down old coremodel generator
* Use public version of jennywrites
* Pull latest thema
* Commit generated Go types
* Add header injection postprocessor
* Move sdboyer/jennywrites to grafana/codejen
* Tweak header output
* Remove dashboard and playlist coremodels
* Fix up backend dashboards devenv test
* Fix TS import patterns to new gen filename
* Update internal imports, remove coremodel registry
* Fix compilation errors, wire generation
* Export and replace the prefix dropper
* More Go struct and field name changes
* Last name fixes, hopefully
* Fix lint errors
* Last lint error
Co-authored-by: Artur Wierzbicki <wierzbicki.artur.94@gmail.com>
2022-11-10 14:36:40 -06:00
"go/ast"
2022-09-14 09:15:09 -05:00
"go/format"
"go/parser"
"go/token"
"os"
"path/filepath"
Reconcile coremodels, entities, objects under new kind framework (#56492)
* Update thema to latest
* Deal with s/Library/*Runtime/
* Commit new, working results of codegen
* We like pointers now
* Always take runtime arg for NewBase()
* Sketchy handwavy pass at entity meta framework
* Little nibbles
* Update pkg/framework/coremodel/entityframework.cue
Co-authored-by: Artur Wierzbicki <wierzbicki.artur.94@gmail.com>
* Move file into new framework location
* Introduce loaders, Go code
* Complete rename to kind
* Flesh out framework, add svg/dashboard examples
* Cruft removal
* Remove generated kind go files from gitignore
* Refine maturity concept, add SlotKind
* Update embed and go deps
* Export PrefixWithGrafanaCUE
* Make the loader actually work, holy crap
* Many small tweaks to type.cue
* Add Apache 2 licensing exceptions for kinds
* Add new kinds dir, start of generator
* Roll back to earlier oapi-codegen
* Introduce new grafana-specific CUE loaders
* Introduce new tidy code generators framework
* Catch up kind framework with tinkering
* Add slices for the generators
* Add write/verify step to main generator
* Many renames
* Split up kind framework cue files
* Use kind.Decl within generated kinds
* Create kind.SomeDecl wrapper type to cache lineages
* Better names again
* Get one generated implemented, hopefully
* Copy dashboard schema into new kind.cue
* Small fixes to make the initial gen work
* Put svg kind in its new home
* Add generated Go dashboard type
* More renames and cleanups
* Add base kind registry and generator
* Stop blacklisting *_gen.go files
This is not the Go best practice, anyway. All we actually want to ignore
for enterprise is generated wire files.
* Change codegen output directories
pkg/kind -> pkg/kinds
pkg/registry/kindreg -> pkg/registry/corekind
* Rename pkg/framework/kind to pkg/kindsys
* Add core structured kind generator
* Add plural and machine names to kind spec
* Copy playlist over to kind system
* Consolidate kindsys files
* Add raw kind generator
* Update CODEOWNERS for kind framework
* Touch up comments a bit
* More docs tweaks
* Remove generated types to reduce noise for review
* Split each generator into its own file
* Rename Slot kind to Composable kind
* Add handwavy types for customkind loading
* Guard against init calls to framework loader
* First pass at doc on extending the kind system
* Improve attribute example in docs
* Fix wire imports
* Add basic TS types generator
* Fix composable kind category def
* No need for a separate file with generate directive
* Catch dashboard schema up
* Rename generator types to something saner and generic
* Make version configurable in ts/go generators
* Add CommonMeta to ease property access
* Add kindsys prop indicating whether lineage is group
* Put all kind categories back in a single file
* Finish with kindsys group props
* Refactor maturity progression per discussion
- Replace "committed" with "merged"
- All kindcats can use all maturity levels, at least for now
* Convert ts veneer index generator to modular system
* Move over to new jennywrites framework
* Strip down old coremodel generator
* Use public version of jennywrites
* Pull latest thema
* Commit generated Go types
* Add header injection postprocessor
* Move sdboyer/jennywrites to grafana/codejen
* Tweak header output
* Remove dashboard and playlist coremodels
* Fix up backend dashboards devenv test
* Fix TS import patterns to new gen filename
* Update internal imports, remove coremodel registry
* Fix compilation errors, wire generation
* Export and replace the prefix dropper
* More Go struct and field name changes
* Last name fixes, hopefully
* Fix lint errors
* Last lint error
Co-authored-by: Artur Wierzbicki <wierzbicki.artur.94@gmail.com>
2022-11-10 14:36:40 -06:00
"regexp"
2022-09-14 09:15:09 -05:00
"strings"
2022-09-29 11:01:02 -05:00
"golang.org/x/tools/go/ast/astutil"
2022-09-14 09:15:09 -05:00
"golang.org/x/tools/imports"
)
type genGoFile struct {
path string
2022-09-29 11:01:02 -05:00
walker astutil . ApplyFunc
2022-09-14 09:15:09 -05:00
in [ ] byte
}
func postprocessGoFile ( cfg genGoFile ) ( [ ] byte , error ) {
fname := filepath . Base ( cfg . path )
buf := new ( bytes . Buffer )
fset := token . NewFileSet ( )
gf , err := parser . ParseFile ( fset , fname , string ( cfg . in ) , parser . ParseComments )
if err != nil {
return nil , fmt . Errorf ( "error parsing generated file: %w" , err )
}
if cfg . walker != nil {
2022-09-29 11:01:02 -05:00
astutil . Apply ( gf , cfg . walker , nil )
2022-09-14 09:15:09 -05:00
err = format . Node ( buf , fset , gf )
if err != nil {
return nil , fmt . Errorf ( "error formatting Go AST: %w" , err )
}
} else {
buf = bytes . NewBuffer ( cfg . in )
}
byt , err := imports . Process ( fname , buf . Bytes ( ) , nil )
if err != nil {
return nil , fmt . Errorf ( "goimports processing failed: %w" , err )
}
// Compare imports before and after; warn about performance if some were added
gfa , _ := parser . ParseFile ( fset , fname , string ( byt ) , parser . ParseComments )
imap := make ( map [ string ] bool )
for _ , im := range gf . Imports {
imap [ im . Path . Value ] = true
}
var added [ ] string
for _ , im := range gfa . Imports {
if ! imap [ im . Path . Value ] {
added = append ( added , im . Path . Value )
}
}
if len ( added ) != 0 {
// TODO improve the guidance in this error if/when we better abstract over imports to generate
fmt . Fprintf ( os . Stderr , "The following imports were added by goimports while generating %s: \n\t%s\nRelying on goimports to find imports significantly slows down code generation. Consider adding these to the relevant template.\n" , cfg . path , strings . Join ( added , "\n\t" ) )
}
return byt , nil
}
Reconcile coremodels, entities, objects under new kind framework (#56492)
* Update thema to latest
* Deal with s/Library/*Runtime/
* Commit new, working results of codegen
* We like pointers now
* Always take runtime arg for NewBase()
* Sketchy handwavy pass at entity meta framework
* Little nibbles
* Update pkg/framework/coremodel/entityframework.cue
Co-authored-by: Artur Wierzbicki <wierzbicki.artur.94@gmail.com>
* Move file into new framework location
* Introduce loaders, Go code
* Complete rename to kind
* Flesh out framework, add svg/dashboard examples
* Cruft removal
* Remove generated kind go files from gitignore
* Refine maturity concept, add SlotKind
* Update embed and go deps
* Export PrefixWithGrafanaCUE
* Make the loader actually work, holy crap
* Many small tweaks to type.cue
* Add Apache 2 licensing exceptions for kinds
* Add new kinds dir, start of generator
* Roll back to earlier oapi-codegen
* Introduce new grafana-specific CUE loaders
* Introduce new tidy code generators framework
* Catch up kind framework with tinkering
* Add slices for the generators
* Add write/verify step to main generator
* Many renames
* Split up kind framework cue files
* Use kind.Decl within generated kinds
* Create kind.SomeDecl wrapper type to cache lineages
* Better names again
* Get one generated implemented, hopefully
* Copy dashboard schema into new kind.cue
* Small fixes to make the initial gen work
* Put svg kind in its new home
* Add generated Go dashboard type
* More renames and cleanups
* Add base kind registry and generator
* Stop blacklisting *_gen.go files
This is not the Go best practice, anyway. All we actually want to ignore
for enterprise is generated wire files.
* Change codegen output directories
pkg/kind -> pkg/kinds
pkg/registry/kindreg -> pkg/registry/corekind
* Rename pkg/framework/kind to pkg/kindsys
* Add core structured kind generator
* Add plural and machine names to kind spec
* Copy playlist over to kind system
* Consolidate kindsys files
* Add raw kind generator
* Update CODEOWNERS for kind framework
* Touch up comments a bit
* More docs tweaks
* Remove generated types to reduce noise for review
* Split each generator into its own file
* Rename Slot kind to Composable kind
* Add handwavy types for customkind loading
* Guard against init calls to framework loader
* First pass at doc on extending the kind system
* Improve attribute example in docs
* Fix wire imports
* Add basic TS types generator
* Fix composable kind category def
* No need for a separate file with generate directive
* Catch dashboard schema up
* Rename generator types to something saner and generic
* Make version configurable in ts/go generators
* Add CommonMeta to ease property access
* Add kindsys prop indicating whether lineage is group
* Put all kind categories back in a single file
* Finish with kindsys group props
* Refactor maturity progression per discussion
- Replace "committed" with "merged"
- All kindcats can use all maturity levels, at least for now
* Convert ts veneer index generator to modular system
* Move over to new jennywrites framework
* Strip down old coremodel generator
* Use public version of jennywrites
* Pull latest thema
* Commit generated Go types
* Add header injection postprocessor
* Move sdboyer/jennywrites to grafana/codejen
* Tweak header output
* Remove dashboard and playlist coremodels
* Fix up backend dashboards devenv test
* Fix TS import patterns to new gen filename
* Update internal imports, remove coremodel registry
* Fix compilation errors, wire generation
* Export and replace the prefix dropper
* More Go struct and field name changes
* Last name fixes, hopefully
* Fix lint errors
* Last lint error
Co-authored-by: Artur Wierzbicki <wierzbicki.artur.94@gmail.com>
2022-11-10 14:36:40 -06:00
type prefixmod struct {
str string
base string
rxp * regexp . Regexp
rxpsuff * regexp . Regexp
}
// PrefixDropper returns an astutil.ApplyFunc that removes the provided prefix
// string when it appears as a leading sequence in type names, var names, and
// comments in a generated Go file.
func PrefixDropper ( prefix string ) astutil . ApplyFunc {
return ( & prefixmod {
str : prefix ,
rxpsuff : regexp . MustCompile ( fmt . Sprintf ( ` %s([a-zA-Z_]+) ` , prefix ) ) ,
rxp : regexp . MustCompile ( fmt . Sprintf ( ` %s([\s.,;-]) ` , prefix ) ) ,
} ) . applyfunc
}
func depoint ( e ast . Expr ) ast . Expr {
if star , is := e . ( * ast . StarExpr ) ; is {
return star . X
}
return e
}
func ( d prefixmod ) applyfunc ( c * astutil . Cursor ) bool {
n := c . Node ( )
switch x := n . ( type ) {
case * ast . ValueSpec :
d . handleExpr ( x . Type )
for _ , id := range x . Names {
d . do ( id )
}
case * ast . TypeSpec :
// Always do typespecs
d . do ( x . Name )
case * ast . Field :
// Don't rename struct fields. We just want to rename type declarations, and
// field value specifications that reference those types.
d . handleExpr ( x . Type )
case * ast . CommentGroup :
for _ , c := range x . List {
c . Text = d . rxpsuff . ReplaceAllString ( c . Text , "$1" )
if d . base != "" {
c . Text = d . rxp . ReplaceAllString ( c . Text , d . base + "$1" )
}
}
}
return true
}
func ( d prefixmod ) handleExpr ( e ast . Expr ) {
// Deref a StarExpr, if there is one
expr := depoint ( e )
switch x := expr . ( type ) {
case * ast . Ident :
d . do ( x )
case * ast . ArrayType :
if id , is := depoint ( x . Elt ) . ( * ast . Ident ) ; is {
d . do ( id )
}
case * ast . MapType :
if id , is := depoint ( x . Key ) . ( * ast . Ident ) ; is {
d . do ( id )
}
if id , is := depoint ( x . Value ) . ( * ast . Ident ) ; is {
d . do ( id )
}
}
}
func ( d prefixmod ) do ( n * ast . Ident ) {
if n . Name != d . str {
n . Name = strings . TrimPrefix ( n . Name , d . str )
} else if d . base != "" {
n . Name = d . base
}
}