diff --git a/kinds/gen.go b/kinds/gen.go index 57abd5cc5d2..4dc69e32799 100644 --- a/kinds/gen.go +++ b/kinds/gen.go @@ -19,8 +19,6 @@ import ( "cuelang.org/go/cue/errors" "github.com/grafana/codejen" "github.com/grafana/cuetsy" - "github.com/grafana/cuetsy/ts" - "github.com/grafana/cuetsy/ts/ast" "github.com/grafana/kindsys" "github.com/grafana/grafana/pkg/codegen" @@ -44,9 +42,7 @@ func main() { &codegen.GoSpecJenny{}, codegen.CoreKindJenny(cuectx.GoCoreKindParentPath, nil), codegen.BaseCoreRegistryJenny(filepath.Join("pkg", "registry", "corekind"), cuectx.GoCoreKindParentPath), - codegen.LatestMajorsOrXJenny( - cuectx.TSCoreKindParentPath, - codegen.TSTypesJenny{ApplyFuncs: []codegen.ApplyFunc{renameSpecNode}}), + codegen.LatestMajorsOrXJenny(cuectx.TSCoreKindParentPath), codegen.TSVeneerIndexJenny(filepath.Join("packages", "grafana-schema", "src")), ) @@ -233,48 +229,3 @@ func loadCueFiles(dirs []os.DirEntry) []cue.Value { return values } - -// renameSpecNode rename spec node from the TS file result -func renameSpecNode(sfg codegen.SchemaForGen, tf *ast.File) { - specidx, specdefidx := -1, -1 - for idx, def := range tf.Nodes { - // Peer through export keywords - if ex, is := def.(ast.ExportKeyword); is { - def = ex.Decl - } - - switch x := def.(type) { - case ast.TypeDecl: - if x.Name.Name == "spec" { - specidx = idx - x.Name.Name = sfg.Name - tf.Nodes[idx] = x - } - case ast.VarDecl: - // Before: - // export const defaultspec: Partial = { - // After: - // / export const defaultPlaylist: Partial = { - if x.Names.Idents[0].Name == "defaultspec" { - specdefidx = idx - x.Names.Idents[0].Name = "default" + sfg.Name - tt := x.Type.(ast.TypeTransformExpr) - tt.Expr = ts.Ident(sfg.Name) - x.Type = tt - tf.Nodes[idx] = x - } - } - } - - if specidx != -1 { - decl := tf.Nodes[specidx] - tf.Nodes = append(append(tf.Nodes[:specidx], tf.Nodes[specidx+1:]...), decl) - } - if specdefidx != -1 { - if specdefidx > specidx { - specdefidx-- - } - decl := tf.Nodes[specdefidx] - tf.Nodes = append(append(tf.Nodes[:specdefidx], tf.Nodes[specdefidx+1:]...), decl) - } -} diff --git a/pkg/codegen/generators.go b/pkg/codegen/generators.go index f4558c48ba7..50b29ffbae6 100644 --- a/pkg/codegen/generators.go +++ b/pkg/codegen/generators.go @@ -15,19 +15,6 @@ type OneToMany codejen.OneToMany[kindsys.Kind] type ManyToOne codejen.ManyToOne[kindsys.Kind] type ManyToMany codejen.ManyToMany[kindsys.Kind] -// ForLatestSchema returns a [SchemaForGen] for the latest schema in the -// provided [kindsys.Kind]'s lineage. -// -// TODO this will be replaced by thema-native constructs -func ForLatestSchema(k kindsys.Kind) SchemaForGen { - comm := k.Props().Common() - return SchemaForGen{ - Name: comm.Name, - Schema: k.Lineage().Latest(), - IsGroup: comm.LineageIsGroup, - } -} - // SlashHeaderMapper produces a FileMapper that injects a comment header onto // a [codejen.File] indicating the main generator that produced it (via the provided // maingen, which should be a path) and the jenny or jennies that constructed the diff --git a/pkg/codegen/jenny_eachmajor.go b/pkg/codegen/jenny_eachmajor.go index e2c60648e32..5fcc83028d2 100644 --- a/pkg/codegen/jenny_eachmajor.go +++ b/pkg/codegen/jenny_eachmajor.go @@ -5,20 +5,16 @@ import ( "path/filepath" "github.com/grafana/codejen" + "github.com/grafana/cuetsy/ts" + "github.com/grafana/cuetsy/ts/ast" "github.com/grafana/kindsys" ) // LatestMajorsOrXJenny returns a jenny that repeats the input for the latest in each major version. -// -// TODO remove forceGroup option, it's a temporary hack to accommodate core kinds -func LatestMajorsOrXJenny(parentdir string, inner codejen.OneToOne[SchemaForGen]) OneToMany { - if inner == nil { - panic("inner jenny must not be nil") - } - +func LatestMajorsOrXJenny(parentdir string) OneToMany { return &lmox{ parentdir: parentdir, - inner: inner, + inner: TSTypesJenny{ApplyFuncs: []ApplyFunc{renameSpecNode}}, } } @@ -56,3 +52,48 @@ func (j *lmox) Generate(kind kindsys.Kind) (codejen.Files, error) { f.From = append(f.From, j) return codejen.Files{*f}, nil } + +// renameSpecNode rename spec node from the TS file result +func renameSpecNode(sfg SchemaForGen, tf *ast.File) { + specidx, specdefidx := -1, -1 + for idx, def := range tf.Nodes { + // Peer through export keywords + if ex, is := def.(ast.ExportKeyword); is { + def = ex.Decl + } + + switch x := def.(type) { + case ast.TypeDecl: + if x.Name.Name == "spec" { + specidx = idx + x.Name.Name = sfg.Name + tf.Nodes[idx] = x + } + case ast.VarDecl: + // Before: + // export const defaultspec: Partial = { + // After: + // / export const defaultPlaylist: Partial = { + if x.Names.Idents[0].Name == "defaultspec" { + specdefidx = idx + x.Names.Idents[0].Name = "default" + sfg.Name + tt := x.Type.(ast.TypeTransformExpr) + tt.Expr = ts.Ident(sfg.Name) + x.Type = tt + tf.Nodes[idx] = x + } + } + } + + if specidx != -1 { + decl := tf.Nodes[specidx] + tf.Nodes = append(append(tf.Nodes[:specidx], tf.Nodes[specidx+1:]...), decl) + } + if specdefidx != -1 { + if specdefidx > specidx { + specdefidx-- + } + decl := tf.Nodes[specdefidx] + tf.Nodes = append(append(tf.Nodes[:specdefidx], tf.Nodes[specdefidx+1:]...), decl) + } +} diff --git a/pkg/codegen/jenny_go_types.go b/pkg/codegen/jenny_go_types.go deleted file mode 100644 index d1d83364a57..00000000000 --- a/pkg/codegen/jenny_go_types.go +++ /dev/null @@ -1,42 +0,0 @@ -package codegen - -import ( - copenapi "cuelang.org/go/encoding/openapi" - "github.com/dave/dst/dstutil" - "github.com/grafana/codejen" - "github.com/grafana/thema/encoding/gocode" - "github.com/grafana/thema/encoding/openapi" -) - -// GoTypesJenny is a [OneToOne] that produces Go types for the provided -// [thema.Schema]. -type GoTypesJenny struct { - ApplyFuncs []dstutil.ApplyFunc - ExpandReferences bool -} - -func (j GoTypesJenny) JennyName() string { - return "GoTypesJenny" -} - -func (j GoTypesJenny) Generate(sfg SchemaForGen) (*codejen.File, error) { - // TODO allow using name instead of machine name in thema generator - b, err := gocode.GenerateTypesOpenAPI(sfg.Schema, &gocode.TypeConfigOpenAPI{ - // TODO will need to account for sanitizing e.g. dashes here at some point - Config: &openapi.Config{ - Group: sfg.IsGroup, - RootName: sfg.Name, - Config: &copenapi.Config{ - ExpandReferences: j.ExpandReferences, - }, - }, - PackageName: sfg.Schema.Lineage().Name(), - ApplyFuncs: append(j.ApplyFuncs, PrefixDropper(sfg.Name)), - }) - - if err != nil { - return nil, err - } - - return codejen.NewFile(sfg.Schema.Lineage().Name()+"_types_gen.go", b, j), nil -} diff --git a/pkg/codegen/latest_jenny.go b/pkg/codegen/latest_jenny.go deleted file mode 100644 index b8a0a618a0e..00000000000 --- a/pkg/codegen/latest_jenny.go +++ /dev/null @@ -1,54 +0,0 @@ -package codegen - -import ( - "fmt" - "path/filepath" - - "github.com/grafana/codejen" - "github.com/grafana/kindsys" -) - -// LatestJenny returns a jenny that runs another jenny for only the latest -// schema in a DefForGen, and prefixes the resulting file with the provided -// parentdir (e.g. "pkg/kinds/") and with a directory based on the kind's -// machine name (e.g. "dashboard/"). -func LatestJenny(parentdir string, inner codejen.OneToOne[SchemaForGen]) OneToOne { - if inner == nil { - panic("inner jenny must not be nil") - } - - return &latestj{ - parentdir: parentdir, - inner: inner, - } -} - -type latestj struct { - parentdir string - inner codejen.OneToOne[SchemaForGen] -} - -func (j *latestj) JennyName() string { - return "LatestJenny" -} - -func (j *latestj) Generate(kind kindsys.Kind) (*codejen.File, error) { - comm := kind.Props().Common() - sfg := SchemaForGen{ - Name: comm.Name, - Schema: kind.Lineage().Latest(), - IsGroup: comm.LineageIsGroup, - } - - f, err := j.inner.Generate(sfg) - if err != nil { - return nil, fmt.Errorf("%s jenny failed on %s schema for %s: %w", j.inner.JennyName(), sfg.Schema.Version(), kind.Props().Common().Name, err) - } - if f == nil || !f.Exists() { - return nil, nil - } - - f.RelativePath = filepath.Join(j.parentdir, comm.MachineName, f.RelativePath) - f.From = append(f.From, j) - return f, nil -} diff --git a/pkg/codegen/tmpl/addenda.tmpl b/pkg/codegen/tmpl/addenda.tmpl deleted file mode 100644 index dc7533b8ea7..00000000000 --- a/pkg/codegen/tmpl/addenda.tmpl +++ /dev/null @@ -1,64 +0,0 @@ - - -//go:embed coremodel.cue -var cueFS embed.FS - -// The current version of the coremodel schema, as declared in coremodel.cue. -// This version determines what schema version is returned from [Coremodel.CurrentSchema], -// and which schema version is used for code generation within the grafana/grafana repository. -// -// The code generator ensures that this is always the latest Thema schema version. -var currentVersion = thema.SV({{ .LatestSeqv }}, {{ .LatestSchv }}) - -// Lineage returns the Thema lineage representing a Grafana {{ .Name }}. -// -// The lineage is the canonical specification of the current {{ .Name }} schema, -// all prior schema versions, and the mappings that allow migration between -// schema versions. -{{- if .IsComposed }}// -// This is the base variant of the schema. It does not include any composed -// plugin schemas.{{ end }} -func Lineage(rt *thema.Runtime, opts ...thema.BindOption) (thema.Lineage, error) { - return cuectx.LoadGrafanaInstancesWithThema(filepath.Join("pkg", "coremodel", "{{ .Name }}"), cueFS, rt, opts...) -} - -var _ thema.LineageFactory = Lineage -var _ coremodel.Interface = &Coremodel{} - -// Coremodel contains the foundational schema declaration for {{ .Name }}s. -// It implements coremodel.Interface. -type Coremodel struct { - lin thema.Lineage -} - -// Lineage returns the canonical {{ .Name }} Lineage. -func (c *Coremodel) Lineage() thema.Lineage { - return c.lin -} - -// CurrentSchema returns the current (latest) {{ .Name }} Thema schema. -func (c *Coremodel) CurrentSchema() thema.Schema { - return thema.SchemaP(c.lin, currentVersion) -} - -// GoType returns a pointer to an empty Go struct that corresponds to -// the current Thema schema. -func (c *Coremodel) GoType() interface{} { - return &Model{} -} - -// New returns a new instance of the {{ .Name }} coremodel. -// -// Note that this function does not cache, and initially loading a Thema lineage -// can be expensive. As such, the Grafana backend should prefer to access this -// coremodel through a registry (pkg/framework/coremodel/registry), which does cache. -func New(rt *thema.Runtime) (*Coremodel, error) { - lin, err := Lineage(rt) - if err != nil { - return nil, err - } - - return &Coremodel{ - lin: lin, - }, nil -} diff --git a/pkg/codegen/tmpl/autogen_header.tmpl b/pkg/codegen/tmpl/autogen_header.tmpl deleted file mode 100644 index c6af378dc5b..00000000000 --- a/pkg/codegen/tmpl/autogen_header.tmpl +++ /dev/null @@ -1,28 +0,0 @@ -{{ if .GenLicense -}} -// Copyright {{ now.Year }} Grafana Labs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -{{ end -}} -// This file is autogenerated. DO NOT EDIT. -{{- if ne .GeneratorPath "" }} -// -// Generated by {{ .GeneratorPath }} -{{- end }} -{{- if ne .LineagePath "" }} -// -// Derived from the Thema lineage declared in {{ .LineagePath }}{{ if ne .LineageCUEPath "" }} at CUE path "{{ .LineageCUEPath }}"{{ end }} -{{- end }} -// -// Run `make gen-cue` from repository root to regenerate. - diff --git a/pkg/codegen/tmpl/coremodel_imports.tmpl b/pkg/codegen/tmpl/coremodel_imports.tmpl deleted file mode 100644 index 40e4aa45211..00000000000 --- a/pkg/codegen/tmpl/coremodel_imports.tmpl +++ /dev/null @@ -1,10 +0,0 @@ -package {{ .PackageName }} - -import ( - "embed" - "path/filepath" - - "github.com/grafana/grafana/pkg/cuectx" - "github.com/grafana/grafana/pkg/framework/coremodel" - "github.com/grafana/thema" -) diff --git a/pkg/codegen/tmpl/cuetsy_multi.tmpl b/pkg/codegen/tmpl/cuetsy_multi.tmpl deleted file mode 100644 index 686a8e55509..00000000000 --- a/pkg/codegen/tmpl/cuetsy_multi.tmpl +++ /dev/null @@ -1,2 +0,0 @@ -{{ template "autogen_header.tmpl" .Header -}} -{{ .Body }} diff --git a/pkg/codegen/tmpl/plugin_lineage_binding.tmpl b/pkg/codegen/tmpl/plugin_lineage_binding.tmpl deleted file mode 100644 index e3d66a9f1ac..00000000000 --- a/pkg/codegen/tmpl/plugin_lineage_binding.tmpl +++ /dev/null @@ -1,12 +0,0 @@ -// The current version of the coremodel schema, as declared in coremodel.cue. -// This version determines what schema version is returned from [Coremodel.CurrentSchema], -// and which schema version is used for code generation within the grafana/grafana repository. -// -// The code generator ensures that this is always the latest Thema schema version. -var currentVersion{{ .SlotName }} = thema.SV({{ .LatestSeqv }}, {{ .LatestSchv }}) - -// {{ .SlotName }}Lineage returns the Thema lineage for the {{ .PluginID }} {{ .PluginType }} plugin's -// {{ .SlotName }} ["github.com/grafana/grafana/pkg/framework/coremodel".Slot] implementation. -func {{ .SlotName }}Lineage(rt *thema.Runtime, opts ...thema.BindOption) (thema.Lineage, error) { - return cuectx.LoadGrafanaInstancesWithThema(filepath.Join("public", "app", "{{ .Name }}"), cueFS, rt, opts...) -} diff --git a/pkg/codegen/tmpl/plugin_lineage_file.tmpl b/pkg/codegen/tmpl/plugin_lineage_file.tmpl deleted file mode 100644 index a14f4c975be..00000000000 --- a/pkg/codegen/tmpl/plugin_lineage_file.tmpl +++ /dev/null @@ -1,59 +0,0 @@ -{{ template "autogen_header.tmpl" .Header -}} -package {{ .PackageName }} - -import ( - "embed" - "fmt" - "path/filepath" - "sync" - - "github.com/grafana/thema" - - "github.com/grafana/grafana/pkg/cuectx" - "github.com/grafana/grafana/pkg/plugins/pfs" -) - -var parseOnce sync.Once -var ptree *pfs.Tree - -//go:embed plugin.{{ if .RootCUE }}cue{{ else }}json{{ end }}{{ if .HasModels }} models.cue{{ end }} -var plugFS embed.FS - -// PluginTree returns the plugin tree representing the statically analyzable contents of the {{ .PluginID }} plugin. -func PluginTree(rt *thema.Runtime) *pfs.Tree { - var err error - if rt == nil || rt == cuectx.GrafanaThemaRuntime() { - parseOnce.Do(func() { - ptree, err = pfs.ParsePluginFS(plugFS, cuectx.GrafanaThemaRuntime()) - }) - } else { - ptree, err = pfs.ParsePluginFS(plugFS, rt) - } - - if err != nil { - // Even the most rudimentary testing in CI ensures this is unreachable - panic(fmt.Errorf("error parsing plugin fs tree: %w", err)) - } - - return ptree -} - -{{ $pluginfo := . }}{{ range $slot := .SlotImpls }} -// {{ .SlotName }}Lineage returns the Thema lineage for the {{ $pluginfo.PluginID }} {{ $pluginfo.PluginType }} plugin's -// {{ .SlotName }} ["github.com/grafana/grafana/pkg/framework/coremodel".Slot] implementation. -func {{ .SlotName }}Lineage(rt *thema.Runtime, opts ...thema.BindOption) (thema.Lineage, error) { - t := PluginTree(rt) - lin, has := t.RootPlugin().SlotImplementations()["{{ .SlotName }}"] - if !has { - panic("unreachable: lineage for {{ .SlotName }} does not exist, but code is only generated for existing lineages") - } - return lin, nil -} - -// The current schema version of the {{ .SlotName }} slot implementation. -// -// Code generation ensures that this is always the version number for the latest schema -// in the {{ .SlotName }} Thema lineage. -var currentVersion{{ .SlotName }} = thema.SV({{ .LatestMajv }}, {{ .LatestMinv }}) - -{{ end }} diff --git a/pkg/codegen/tmpl/plugin_registry_ref.tmpl b/pkg/codegen/tmpl/plugin_registry_ref.tmpl deleted file mode 100644 index 68ef98cbded..00000000000 --- a/pkg/codegen/tmpl/plugin_registry_ref.tmpl +++ /dev/null @@ -1,16 +0,0 @@ -{{ template "autogen_header.tmpl" .Header -}} -package registry - -import ( - "github.com/grafana/grafana/pkg/plugins/pfs" - "github.com/grafana/thema" - {{ range .Plugins }} - {{ if .NoAlias }}{{ .PkgName }} {{end}}"{{ .Path }}"{{ end }} -) - -func coreTreeLoaders() []func(*thema.Runtime) *pfs.Tree{ - return []func(*thema.Runtime) *pfs.Tree{ - {{- range .Plugins }} - {{ .PkgName }}.PluginTree,{{ end }} - } -} diff --git a/public/app/plugins/gen.go b/public/app/plugins/gen.go index b8771d48753..264152e442d 100644 --- a/public/app/plugins/gen.go +++ b/public/app/plugins/gen.go @@ -79,16 +79,6 @@ func main() { } } -func adaptToPipeline(j codejen.OneToOne[corecodegen.SchemaForGen]) codejen.OneToOne[*pfs.PluginDecl] { - return codejen.AdaptOneToOne(j, func(pd *pfs.PluginDecl) corecodegen.SchemaForGen { - return corecodegen.SchemaForGen{ - Name: strings.ReplaceAll(pd.PluginMeta.Name, " ", ""), - Schema: pd.Lineage.Latest(), - IsGroup: pd.SchemaInterface.IsGroup, - } - }) -} - func kind2pd(rt *thema.Runtime, j codejen.OneToOne[kindsys.Kind]) codejen.OneToOne[*pfs.PluginDecl] { return codejen.AdaptOneToOne(j, func(pd *pfs.PluginDecl) kindsys.Kind { kd, err := kindsys.BindComposable(rt, pd.KindDecl)