Answer architecture round 3: the generated header names go generate, one sorted-keys helper everywhere, one site constructor, and an inline folder reference refused before anything loads
This commit is contained in:
@@ -203,13 +203,17 @@ func categorySites(root *folder) []categorySite {
|
|||||||
walk(append(dir[:len(dir):len(dir)], name), sub)
|
walk(append(dir[:len(dir):len(dir)], name), sub)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
out = append(out, categorySite{dir: dir, path: join(strings.Join(dir, "."), name), in: g, n: g.children[name]})
|
out = append(out, siteIn(dir, g, name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
walk(nil, root)
|
walk(nil, root)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func siteIn(dir []string, in *folder, name string) categorySite {
|
||||||
|
return categorySite{dir: dir, path: join(strings.Join(dir, "."), name), in: in, n: in.children[name]}
|
||||||
|
}
|
||||||
|
|
||||||
func sitesScope(sites []categorySite) nodeScope {
|
func sitesScope(sites []categorySite) nodeScope {
|
||||||
return func(fn func(path string, n node) error) error {
|
return func(fn func(path string, n node) error) error {
|
||||||
for _, s := range sites {
|
for _, s := range sites {
|
||||||
|
|||||||
+1
-6
@@ -180,12 +180,7 @@ func paths(n node) []string {
|
|||||||
func tablePaths(t *table) []string {
|
func tablePaths(t *table) []string {
|
||||||
out := append([]string{""}, t.header...)
|
out := append([]string{""}, t.header...)
|
||||||
sort.Strings(out[1:])
|
sort.Strings(out[1:])
|
||||||
children := make([]string, 0, len(t.children))
|
for _, name := range sortedNames(t.children) {
|
||||||
for name := range t.children {
|
|
||||||
children = append(children, name)
|
|
||||||
}
|
|
||||||
sort.Strings(children)
|
|
||||||
for _, name := range children {
|
|
||||||
for _, p := range paths(t.children[name]) {
|
for _, p := range paths(t.children[name]) {
|
||||||
out = append(out, join(name, p))
|
out = append(out, join(name, p))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,6 +152,9 @@ func inputValue(input string) (any, error) {
|
|||||||
// binding's.
|
// binding's.
|
||||||
func bindInline(root *folder, n node, label string, typedByGo bool) error {
|
func bindInline(root *folder, n node, label string, typedByGo bool) error {
|
||||||
scope := inlineScope(n, label)
|
scope := inlineScope(n, label)
|
||||||
|
if err := refuseFolderRefs(scope); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
loadShipped(root, unloadedReads(root, nil, scope))
|
loadShipped(root, unloadedReads(root, nil, scope))
|
||||||
return binding{
|
return binding{
|
||||||
scope: scope,
|
scope: scope,
|
||||||
@@ -166,10 +169,9 @@ func bindInline(root *folder, n node, label string, typedByGo bool) error {
|
|||||||
}.bind()
|
}.bind()
|
||||||
}
|
}
|
||||||
|
|
||||||
// linkNodeRefs binds the references in an inline node's templates against the
|
// refuseFolderRefs refuses a reference an inline node writes from a folder, which it has none of.
|
||||||
// loaded tree.
|
func refuseFolderRefs(scope nodeScope) error {
|
||||||
func linkNodeRefs(scope nodeScope, root map[string]node) error {
|
return scope(func(path string, m node) error {
|
||||||
if err := scope(func(path string, m node) error {
|
|
||||||
t, ok := m.(*template)
|
t, ok := m.(*template)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
@@ -183,7 +185,18 @@ func linkNodeRefs(scope nodeScope, root map[string]node) error {
|
|||||||
return fmt.Errorf("%s: reference {%s}: an inline template has no folder; write {/%s}", path, name, rest)
|
return fmt.Errorf("%s: reference {%s}: an inline template has no folder; write {/%s}", path, name, rest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// linkNodeRefs binds the references in an inline node's templates against the
|
||||||
|
// loaded tree.
|
||||||
|
func linkNodeRefs(scope nodeScope, root map[string]node) error {
|
||||||
|
if err := scope(func(path string, m node) error {
|
||||||
|
if t, ok := m.(*template); ok {
|
||||||
return linkTemplate(nil, path, "", t, root)
|
return linkTemplate(nil, path, "", t, root)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-7
@@ -3,7 +3,6 @@ package fejkdata
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// checkNameReads refuses each binding of t that checkUses refuses, and a read such as {n} whose
|
// checkNameReads refuses each binding of t that checkUses refuses, and a read such as {n} whose
|
||||||
@@ -117,12 +116,7 @@ func (b *nameBinding) checkTemplateOnce(read string, t *template, key string) er
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
heads := make([]string, 0, len(fresh))
|
for _, head := range sortedNames(fresh) {
|
||||||
for head := range fresh {
|
|
||||||
heads = append(heads, head)
|
|
||||||
}
|
|
||||||
sort.Strings(heads)
|
|
||||||
for _, head := range heads {
|
|
||||||
if by, kept := b.addressed[join(key, head)]; kept && fresh[head] > 1 {
|
if by, kept := b.addressed[join(key, head)]; kept && fresh[head] > 1 {
|
||||||
return fmt.Errorf("{%s} renders field %q twice, so {%s} cannot say which draw it reads; drop {%s} or {%s}", read, head, by, read, by)
|
return fmt.Errorf("{%s} renders field %q twice, so {%s} cannot say which draw it reads; drop {%s} or {%s}", read, head, by, read, by)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-6
@@ -11,12 +11,7 @@ import (
|
|||||||
// docs/decisions.md#one-name-one-meaning
|
// docs/decisions.md#one-name-one-meaning
|
||||||
func TestNoFunctionSpellsAMethod(t *testing.T) {
|
func TestNoFunctionSpellsAMethod(t *testing.T) {
|
||||||
funcs, methods := declaredCalls(namespaceFiles(t))
|
funcs, methods := declaredCalls(namespaceFiles(t))
|
||||||
names := make([]string, 0, len(funcs))
|
for _, name := range sortedNames(funcs) {
|
||||||
for name := range funcs {
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
|
||||||
sort.Strings(names)
|
|
||||||
for _, name := range names {
|
|
||||||
if recv := methods[name]; len(recv) > 0 {
|
if recv := methods[name]; len(recv) > 0 {
|
||||||
sort.Strings(recv)
|
sort.Strings(recv)
|
||||||
t.Errorf("func %s is spelled by %s too; name them apart", name, strings.Join(recv, " and "))
|
t.Errorf("func %s is spelled by %s too; name them apart", name, strings.Join(recv, " and "))
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package fejkdata
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -470,11 +469,7 @@ func unreachableInChoice(c *choice, want string) error {
|
|||||||
if len(c.shared) == 0 {
|
if len(c.shared) == 0 {
|
||||||
return fmt.Errorf("no variant of this %d-way choice carries %q", len(c.items), want)
|
return fmt.Errorf("no variant of this %d-way choice carries %q", len(c.items), want)
|
||||||
}
|
}
|
||||||
offered := make([]string, 0, len(c.shared))
|
offered := sortedNames(c.shared)
|
||||||
for p := range c.shared {
|
|
||||||
offered = append(offered, p)
|
|
||||||
}
|
|
||||||
sort.Strings(offered)
|
|
||||||
return fmt.Errorf("not every variant of this %d-way choice carries %q; all carry %v", len(c.items), want, offered)
|
return fmt.Errorf("not every variant of this %d-way choice carries %q; all carry %v", len(c.items), want, offered)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-7
@@ -2,7 +2,6 @@ package fejkdata
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -109,12 +108,7 @@ func readsFact(n node) string {
|
|||||||
if len(set) == 0 {
|
if len(set) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
keys := make([]string, 0, len(set))
|
return "\treads " + strings.Join(sortedNames(set), " ")
|
||||||
for k := range set {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
return "\treads " + strings.Join(keys, " ")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShippedShapeNamesReads(t *testing.T) {
|
func TestShippedShapeNamesReads(t *testing.T) {
|
||||||
|
|||||||
+1
-1
@@ -139,7 +139,7 @@ func (u unloadedCategory) load() (categorySite, error) {
|
|||||||
return categorySite{}, err
|
return categorySite{}, err
|
||||||
}
|
}
|
||||||
delete(u.in.unloaded, u.name)
|
delete(u.in.unloaded, u.name)
|
||||||
return categorySite{dir: u.dir, path: join(strings.Join(u.dir, "."), u.name), in: u.in, n: u.in.children[u.name]}, nil
|
return siteIn(u.dir, u.in, u.name), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// linkedTables is the tables beside u that link to it or that it links to: its parent, and
|
// linkedTables is the tables beside u that link to it or that it links to: its parent, and
|
||||||
|
|||||||
+2
-2
@@ -66,7 +66,7 @@ func TestShippedIndexIsCurrent(t *testing.T) {
|
|||||||
|
|
||||||
func shippedIndexSource(whole *Generator) ([]byte, error) {
|
func shippedIndexSource(whole *Generator) ([]byte, error) {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
b.WriteString("// Code generated by TestShippedIndexIsCurrent with REPIN=1. DO NOT EDIT.\n\npackage fejkdata\n\nvar shippedIndex = map[string]shippedEntry{\n")
|
b.WriteString("// Code generated by go generate. DO NOT EDIT.\n\npackage fejkdata\n\nvar shippedIndex = map[string]shippedEntry{\n")
|
||||||
for _, s := range categorySites(&whole.root) {
|
for _, s := range categorySites(&whole.root) {
|
||||||
fmt.Fprintf(&b, "%q: {", s.path)
|
fmt.Fprintf(&b, "%q: {", s.path)
|
||||||
if t, isTable := s.n.(*table); isTable && t.parentIndex >= 0 {
|
if t, isTable := s.n.(*table); isTable && t.parentIndex >= 0 {
|
||||||
@@ -183,7 +183,7 @@ func TestOnDemandRendersAsTheWholeLoad(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestEveryShippedCategoryLoadsAlone(t *testing.T) {
|
func TestEveryShippedCategoryLoadsAlone(t *testing.T) {
|
||||||
for p := range shippedIndex {
|
for _, p := range sortedNames(shippedIndex) {
|
||||||
f, err := New()
|
f, err := New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("New() = %v", err)
|
t.Fatalf("New() = %v", err)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// Code generated by TestShippedIndexIsCurrent with REPIN=1. DO NOT EDIT.
|
// Code generated by go generate. DO NOT EDIT.
|
||||||
|
|
||||||
package fejkdata
|
package fejkdata
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user