From 7b2d049512a2fdb4e5e43fdb3e90180856e00618 Mon Sep 17 00:00:00 2001 From: Wen Bo Li <50884368+wenovus@users.noreply.github.com> Date: Tue, 30 Jun 2020 13:42:29 -0700 Subject: [PATCH] Add option to split GoStructs by number of files (#409) * Split GoStructs by number of files instead of by first letter * Remove splitting GoStructs file by leading letter --- generator/generator.go | 144 ++++++----- generator/generator_test.go | 232 +++++++++++++++--- ypathgen/pathgen.go | 20 +- .../structs/openconfig-simple-30.path-txt | 32 +++ .../structs/openconfig-simple-31.path-txt | 172 ++++++++++++- .../structs/openconfig-simple-32.path-txt | 180 -------------- 6 files changed, 477 insertions(+), 303 deletions(-) diff --git a/generator/generator.go b/generator/generator.go index 6746cb369..f9cb9f3a6 100644 --- a/generator/generator.go +++ b/generator/generator.go @@ -21,6 +21,7 @@ import ( "flag" "fmt" "io" + "math" "os" "path/filepath" "strings" @@ -41,13 +42,9 @@ const ( schemaFn = "schema.go" // interfaceFn is the filename to be used for interface code when outputting to a directory. interfaceFn = "union.go" - // methodFn is the filename to be used for methods related to the structs when outputting - // to a directory. - methodFn = "methods.go" - // structBaseFn is the base filename to be used for files containing structs when outputting - // to a directory. Structs are divided alphabetically and the first character appended to the - // base specified in this value - e.g., structs beginning with "A" are stored in {structBaseFnA}.go. - structBaseFn = "structs_" + // structsFileFmt is the format string filename (missing index) to be + // used for files containing structs when outputting to a directory. + structsFileFmt = "structs-%d.go" // pathStructsFileFmt is the format string filename (missing index) to // be used for the path structs when path struct code is output to a directory. pathStructsFileFmt = "path_structs-%d.go" @@ -57,6 +54,7 @@ var ( generateGoStructs = flag.Bool("generate_structs", true, "If true, then Go code for YANG path construction (schema/Go structs) will be generated.") generatePathStructs = flag.Bool("generate_path_structs", false, "If true, then Go code for YANG path construction (path structs) will be generated.") ocStructsOutputFile = flag.String("output_file", "", "The file that the generated Go code for manipulating YANG data (schema/Go structs) should be written to. Specify \"-\" for stdout.") + structsFileN = flag.Int("structs_split_files_count", 0, "The number of files to split the generated schema structs into when output_file is specified.") ocPathStructsOutputFile = flag.String("path_structs_output_file", "", "The file that the generated Go code for YANG path construction (path structs) will be generated. Specify \"-\" for stdout.") pathStructsFileN = flag.Int("path_structs_split_files_count", 0, "The number of files to split the generated path structs into when output_file is specified for generating path structs") outputDir = flag.String("output_dir", "", "The directory that the generated Go code should be written to. This is common between schema structs and path structs.") @@ -135,86 +133,76 @@ func writeGoPathCodeSingleFile(w io.Writer, pathCode *ypathgen.GeneratedPathCode return err } -// writeIfNotEmpty writes the string s to b if it has a non-zero length. -func writeIfNotEmpty(b io.StringWriter, s string) { - if len(s) != 0 { - b.WriteString(s) +// splitCodeByFileN generates a map, keyed by filename, to a string containing +// the code to be output to that filename. It allows division of a +// ygen.GeneratedGoCode struct into a set of source files. It divides the +// methods, interfaces, and enumeration code snippets into their own files. +// Structs are output into files by splitting them evenly among the input split +// number. +func splitCodeByFileN(goCode *ygen.GeneratedGoCode, fileN int) (map[string]string, error) { + structN := len(goCode.Structs) + if fileN < 1 || fileN > structN { + return nil, fmt.Errorf("requested %d files, but must be between 1 and %d (number of schema structs)", fileN, structN) } -} - -// codeOut describes an output file for Go code. -type codeOut struct { - // contents is the code that is contained in the output file. - contents string - // oneoffHeader indicates whether the one-off header should be included in this - // file. - oneoffHeader bool -} -// makeOutputSpec generates a map, keyed by filename, to a codeOut struct containing -// the code to be output to that filename. It allows division of a ygen.GeneratedGoCode -// struct into a set of source files. It divides the methods, interfaces, and enumeration -// code snippets into their own files. Structs are output into files dependent on the -// first letter of their name within the code. -func makeOutputSpec(goCode *ygen.GeneratedGoCode) map[string]codeOut { - var methodCode, interfaceCode strings.Builder - structCode := map[byte]*strings.Builder{} - for _, s := range goCode.Structs { - // Index by the first character of the struct. - fc := s.StructName[0] - if _, ok := structCode[fc]; !ok { - structCode[fc] = &strings.Builder{} - } - cs := structCode[fc] - writeIfNotEmpty(cs, s.StructDef) - writeIfNotEmpty(cs, fmt.Sprintf("%s\n", s.ListKeys)) - writeIfNotEmpty(&methodCode, fmt.Sprintf("%s\n", s.Methods)) - writeIfNotEmpty(&interfaceCode, fmt.Sprintf("%s\n", s.Interfaces)) + out := map[string]string{ + schemaFn: goCode.JSONSchemaCode, + enumFn: strings.Join(goCode.Enums, "\n"), } - emap := &strings.Builder{} - writeIfNotEmpty(emap, goCode.EnumMap) - if emap.Len() != 0 { - emap.WriteString("\n") + var structFiles []string + var code, interfaceCode strings.Builder + structsPerFile := int(math.Ceil(float64(structN) / float64(fileN))) + // Empty files could appear with certain structN/fileN combinations due + // to the ceiling numbers being used for structsPerFile. + // e.g. 4/3 gives two files of two structs. + // This is a little more complex, but spreads out the structs more evenly. + // If we instead use the floor number, and put all remainder structs in + // the last file, we might double the last file's number of structs if we get unlucky. + // e.g. 99/10 assigns 18 structs to the last file. + emptyFiles := fileN - int(math.Ceil(float64(structN)/float64(structsPerFile))) + code.WriteString(goCode.OneOffHeader) + for i, s := range goCode.Structs { + code.WriteString(s.StructDef) + code.WriteString(s.ListKeys) + code.WriteString("\n") + code.WriteString(s.Methods) + if s.Methods != "" { + code.WriteString("\n") + } + interfaceCode.WriteString(s.Interfaces) + if s.Interfaces != "" { + interfaceCode.WriteString("\n") + } + // The last file contains the remainder of the structs. + if i == structN-1 || (i+1)%structsPerFile == 0 { + structFiles = append(structFiles, code.String()) + code.Reset() + } } - writeIfNotEmpty(emap, goCode.EnumTypeMap) - - out := map[string]codeOut{ - enumMapFn: {contents: emap.String()}, - schemaFn: {contents: goCode.JSONSchemaCode}, - interfaceFn: {contents: interfaceCode.String()}, - methodFn: {contents: methodCode.String(), oneoffHeader: true}, - enumFn: {contents: strings.Join(goCode.Enums, "\n")}, + for i := 0; i != emptyFiles; i++ { + structFiles = append(structFiles, "") } - for fn, code := range structCode { - out[fmt.Sprintf("%s%c.go", structBaseFn, fn)] = codeOut{ - contents: code.String(), - } + for i, structFile := range structFiles { + out[fmt.Sprintf(structsFileFmt, i)] = structFile } - return out -} + code.Reset() + code.WriteString(goCode.EnumMap) + if code.Len() != 0 { + code.WriteString("\n") + } + code.WriteString(goCode.EnumTypeMap) -// writeGoCodeMultipleFiles writes the input goCode to a set of files as specified -// by specification returned by output spec. -func writeGoCodeMultipleFiles(dir string, goCode *ygen.GeneratedGoCode) error { - out := makeOutputSpec(goCode) + out[enumMapFn] = code.String() + out[interfaceFn] = interfaceCode.String() - for fn, f := range out { - if len(f.contents) == 0 { - continue - } - fh := genutil.OpenFile(filepath.Join(dir, fn)) - defer genutil.SyncFile(fh) - fmt.Fprintln(fh, goCode.CommonHeader) - if f.oneoffHeader { - fmt.Fprintln(fh, goCode.OneOffHeader) - } - fmt.Fprintln(fh, f.contents) + for name, code := range out { + out[name] = goCode.CommonHeader + code } - return nil + return out, nil } // writeFiles creates or truncates files in a given base directory and writes @@ -361,7 +349,13 @@ func main() { writeGoCodeSingleFile(outfh, generatedGoCode) case generateGoStructsMultipleFiles: // Write the Go code to a series of output files. - writeGoCodeMultipleFiles(*outputDir, generatedGoCode) + out, err := splitCodeByFileN(generatedGoCode, *structsFileN) + if err != nil { + log.Exitf("ERROR writing split GoStruct Code: %v\n", err) + } + if err := writeFiles(*outputDir, out); err != nil { + log.Exitf("Error while writing schema struct files: %v", err) + } } } diff --git a/generator/generator_test.go b/generator/generator_test.go index 6ce1a8c13..3a320829f 100644 --- a/generator/generator_test.go +++ b/generator/generator_test.go @@ -21,6 +21,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/kylelemons/godebug/pretty" + "github.com/openconfig/gnmi/errdiff" "github.com/openconfig/ygot/ygen" "github.com/openconfig/ygot/ypathgen" ) @@ -91,14 +92,18 @@ map } } -func TestMakeOutputSpec(t *testing.T) { +func TestSplitCodeByFileN(t *testing.T) { tests := []struct { - name string - in *ygen.GeneratedGoCode - want map[string]codeOut + name string + in *ygen.GeneratedGoCode + inFileN int + want map[string]string + wantErrSubstring string }{{ name: "simple struct with all only structs populated", in: &ygen.GeneratedGoCode{ + CommonHeader: "common_header\n", + OneOffHeader: "oneoff_header\n", Structs: []ygen.GoStructCodeSnippet{{ StructName: "name", StructDef: "def\n", @@ -107,17 +112,49 @@ func TestMakeOutputSpec(t *testing.T) { Interfaces: "interfaces", }}, }, - want: map[string]codeOut{ - enumMapFn: {}, - enumFn: {}, - schemaFn: {}, - interfaceFn: {contents: "interfaces\n"}, - methodFn: {contents: "methods\n", oneoffHeader: true}, - fmt.Sprintf("%sn.go", structBaseFn): {contents: "def\nname_key\n"}, + inFileN: 1, + want: map[string]string{ + enumMapFn: "common_header\n", + enumFn: "common_header\n", + schemaFn: "common_header\n", + interfaceFn: "common_header\ninterfaces\n", + fmt.Sprintf(structsFileFmt, 0): "common_header\noneoff_header\ndef\nname_key\nmethods\n", + }, + }, { + name: "less than 1 file requested for splitting", + in: &ygen.GeneratedGoCode{ + CommonHeader: "common_header\n", + OneOffHeader: "oneoff_header\n", + Structs: []ygen.GoStructCodeSnippet{{ + StructName: "name", + StructDef: "def\n", + ListKeys: "name_key", + Methods: "methods", + Interfaces: "interfaces", + }}, }, + inFileN: 0, + wantErrSubstring: "requested 0 files", + }, { + name: "more than # of structs files requested for splitting", + in: &ygen.GeneratedGoCode{ + CommonHeader: "common_header\n", + OneOffHeader: "oneoff_header\n", + Structs: []ygen.GoStructCodeSnippet{{ + StructName: "name", + StructDef: "def\n", + ListKeys: "name_key", + Methods: "methods", + Interfaces: "interfaces", + }}, + }, + inFileN: 2, + wantErrSubstring: "requested 2 files", }, { name: "two structs with enums populated", in: &ygen.GeneratedGoCode{ + CommonHeader: "common_header\n", + OneOffHeader: "oneoff_header\n", Structs: []ygen.GoStructCodeSnippet{{ StructName: "s1", StructDef: "s1def\n", @@ -134,17 +171,19 @@ func TestMakeOutputSpec(t *testing.T) { Enums: []string{"enum1", "enum2"}, EnumMap: "enummap", }, - want: map[string]codeOut{ - enumMapFn: {contents: "enummap\n"}, - enumFn: {contents: "enum1\nenum2"}, - schemaFn: {}, - interfaceFn: {contents: "s1interfaces\ns2interfaces\n"}, - fmt.Sprintf("%ss.go", structBaseFn): {contents: "s1def\ns1key\ns2def\ns2key\n"}, - methodFn: {contents: "s1methods\ns2methods\n", oneoffHeader: true}, + inFileN: 1, + want: map[string]string{ + enumMapFn: "common_header\nenummap\n", + enumFn: "common_header\nenum1\nenum2", + schemaFn: "common_header\n", + interfaceFn: "common_header\ns1interfaces\ns2interfaces\n", + fmt.Sprintf(structsFileFmt, 0): "common_header\noneoff_header\ns1def\ns1key\ns1methods\ns2def\ns2key\ns2methods\n", }, }, { - name: "two structs, different starting letters", + name: "two structs, separated into two files", in: &ygen.GeneratedGoCode{ + CommonHeader: "common_header\n", + OneOffHeader: "oneoff_header\n", Structs: []ygen.GoStructCodeSnippet{{ StructName: "s1", StructDef: "s1def\n", @@ -160,22 +199,153 @@ func TestMakeOutputSpec(t *testing.T) { }}, JSONSchemaCode: "schema", }, - want: map[string]codeOut{ - enumMapFn: {}, - enumFn: {}, - schemaFn: {contents: "schema"}, - interfaceFn: {contents: "s1interfaces\nq2interfaces\n"}, - fmt.Sprintf("%ss.go", structBaseFn): {contents: "s1def\ns1key\n"}, - fmt.Sprintf("%sq.go", structBaseFn): {contents: "q2def\nq2key\n"}, - methodFn: {contents: "s1methods\nq2methods\n", oneoffHeader: true}, + inFileN: 2, + want: map[string]string{ + enumMapFn: "common_header\n", + enumFn: "common_header\n", + schemaFn: "common_header\nschema", + interfaceFn: "common_header\ns1interfaces\nq2interfaces\n", + fmt.Sprintf(structsFileFmt, 0): "common_header\noneoff_header\ns1def\ns1key\ns1methods\n", + fmt.Sprintf(structsFileFmt, 1): "common_header\nq2def\nq2key\nq2methods\n", + }, + }, { + name: "five structs, separated into four files", + in: &ygen.GeneratedGoCode{ + CommonHeader: "common_header\n", + OneOffHeader: "oneoff_header\n", + Structs: []ygen.GoStructCodeSnippet{{ + StructName: "s1", + StructDef: "s1def\n", + ListKeys: "s1key", + Methods: "s1methods", + Interfaces: "s1interfaces", + }, { + StructName: "s2", + StructDef: "s2def\n", + ListKeys: "s2key", + Methods: "s2methods", + Interfaces: "s2interfaces", + }, { + StructName: "s3", + StructDef: "s3def\n", + ListKeys: "s3key", + }, { + StructName: "s4", + StructDef: "s4def\n", + ListKeys: "s4key", + }, { + StructName: "s5", + StructDef: "s5def\n", + ListKeys: "s5key", + }}, + JSONSchemaCode: "schema", + }, + inFileN: 4, + want: map[string]string{ + enumMapFn: "common_header\n", + enumFn: "common_header\n", + schemaFn: "common_header\nschema", + interfaceFn: "common_header\ns1interfaces\ns2interfaces\n", + fmt.Sprintf(structsFileFmt, 0): "common_header\noneoff_header\ns1def\ns1key\ns1methods\ns2def\ns2key\ns2methods\n", + fmt.Sprintf(structsFileFmt, 1): "common_header\ns3def\ns3key\ns4def\ns4key\n", + fmt.Sprintf(structsFileFmt, 2): "common_header\ns5def\ns5key\n", + fmt.Sprintf(structsFileFmt, 3): "common_header\n", + }, + }, { + name: "five structs, separated into three files", + in: &ygen.GeneratedGoCode{ + CommonHeader: "common_header\n", + OneOffHeader: "oneoff_header\n", + Structs: []ygen.GoStructCodeSnippet{{ + StructName: "s1", + StructDef: "s1def\n", + ListKeys: "s1key", + Methods: "s1methods", + Interfaces: "s1interfaces", + }, { + StructName: "s2", + StructDef: "s2def\n", + ListKeys: "s2key", + Methods: "s2methods", + Interfaces: "s2interfaces", + }, { + StructName: "s3", + StructDef: "s3def\n", + ListKeys: "s3key", + }, { + StructName: "s4", + StructDef: "s4def\n", + ListKeys: "s4key", + }, { + StructName: "s5", + StructDef: "s5def\n", + ListKeys: "s5key", + }}, + JSONSchemaCode: "schema", + }, + inFileN: 3, + want: map[string]string{ + enumMapFn: "common_header\n", + enumFn: "common_header\n", + schemaFn: "common_header\nschema", + interfaceFn: "common_header\ns1interfaces\ns2interfaces\n", + fmt.Sprintf(structsFileFmt, 0): "common_header\noneoff_header\ns1def\ns1key\ns1methods\ns2def\ns2key\ns2methods\n", + fmt.Sprintf(structsFileFmt, 1): "common_header\ns3def\ns3key\ns4def\ns4key\n", + fmt.Sprintf(structsFileFmt, 2): "common_header\ns5def\ns5key\n", + }, + }, { + name: "five structs, separated into two files", + in: &ygen.GeneratedGoCode{ + CommonHeader: "common_header\n", + OneOffHeader: "oneoff_header\n", + Structs: []ygen.GoStructCodeSnippet{{ + StructName: "s1", + StructDef: "s1def\n", + ListKeys: "s1key", + Methods: "s1methods", + Interfaces: "s1interfaces", + }, { + StructName: "s2", + StructDef: "s2def\n", + ListKeys: "s2key", + Methods: "s2methods", + Interfaces: "s2interfaces", + }, { + StructName: "s3", + StructDef: "s3def\n", + ListKeys: "s3key", + }, { + StructName: "s4", + StructDef: "s4def\n", + ListKeys: "s4key", + }, { + StructName: "s5", + StructDef: "s5def\n", + ListKeys: "s5key", + }}, + JSONSchemaCode: "schema", + }, + inFileN: 2, + want: map[string]string{ + enumMapFn: "common_header\n", + enumFn: "common_header\n", + schemaFn: "common_header\nschema", + interfaceFn: "common_header\ns1interfaces\ns2interfaces\n", + fmt.Sprintf(structsFileFmt, 0): "common_header\noneoff_header\ns1def\ns1key\ns1methods\ns2def\ns2key\ns2methods\ns3def\ns3key\n", + fmt.Sprintf(structsFileFmt, 1): "common_header\ns4def\ns4key\ns5def\ns5key\n", }, }} for _, tt := range tests { - got := makeOutputSpec(tt.in) - if diff := pretty.Compare(got, tt.want); diff != "" { - t.Errorf("%s: makeOutputSpec(%v): did not get expected output, diff (-got,+want):\n%s", tt.name, tt.in, diff) - } + t.Run(tt.name, func(t *testing.T) { + got, err := splitCodeByFileN(tt.in, tt.inFileN) + if diff := errdiff.Substring(err, tt.wantErrSubstring); diff != "" { + t.Fatalf("did not get expected error, %v", diff) + } + if diff := pretty.Compare(got, tt.want); diff != "" { + t.Errorf("splitCodeByFileN(%v): did not get expected output, diff (-got,+want):\n%s", tt.in, diff) + } + }) } } diff --git a/ypathgen/pathgen.go b/ypathgen/pathgen.go index 3d8e1096a..0f2dae6ae 100644 --- a/ypathgen/pathgen.go +++ b/ypathgen/pathgen.go @@ -24,6 +24,7 @@ package ypathgen import ( "fmt" + "math" "sort" "strings" "text/template" @@ -280,20 +281,29 @@ func (genCode GeneratedPathCode) SplitFiles(fileN int) ([]string, error) { } files := make([]string, 0, fileN) - structsPerFile := structN / fileN + structsPerFile := int(math.Ceil(float64(structN) / float64(fileN))) + // Empty files could appear with certain structN/fileN combinations due + // to the ceiling numbers being used for structsPerFile. + // e.g. 4/3 gives two files of two structs. + // This is a little more complex, but spreads out the structs more evenly. + // If we instead use the floor number, and put all remainder structs in + // the last file, we might double the last file's number of structs if we get unlucky. + // e.g. 99/10 assigns 18 structs to the last file. + emptyFiles := fileN - int(math.Ceil(float64(structN)/float64(structsPerFile))) var gotCode strings.Builder gotCode.WriteString(genCode.CommonHeader) - for i, gotStruct := range genCode.Structs { + gotCode.WriteString(gotStruct.String()) // The last file contains the remainder of the structs. - if i%structsPerFile == 0 && i >= structsPerFile && i < structsPerFile*fileN { + if i == structN-1 || (i+1)%structsPerFile == 0 { files = append(files, gotCode.String()) gotCode.Reset() gotCode.WriteString(genCode.CommonHeader) } - gotCode.WriteString(gotStruct.String()) } - files = append(files, gotCode.String()) + for i := 0; i != emptyFiles; i++ { + files = append(files, genCode.CommonHeader) + } return files, nil } diff --git a/ypathgen/testdata/structs/openconfig-simple-30.path-txt b/ypathgen/testdata/structs/openconfig-simple-30.path-txt index 8286770f1..9ecc4e05d 100644 --- a/ypathgen/testdata/structs/openconfig-simple-30.path-txt +++ b/ypathgen/testdata/structs/openconfig-simple-30.path-txt @@ -45,3 +45,35 @@ func (n *DevicePath) RemoteContainer() *RemoteContainerPath { ), } } + +// ParentPath represents the /openconfig-simple/parent YANG schema element. +type ParentPath struct { + *ygot.NodePath +} + +// ParentPathAny represents the wildcard version of the /openconfig-simple/parent YANG schema element. +type ParentPathAny struct { + *ygot.NodePath +} + +// Child returns from ParentPath the path struct for its child "child". +func (n *ParentPath) Child() *Parent_ChildPath { + return &Parent_ChildPath{ + NodePath: ygot.NewNodePath( + []string{"child"}, + map[string]interface{}{}, + n, + ), + } +} + +// Child returns from ParentPathAny the path struct for its child "child". +func (n *ParentPathAny) Child() *Parent_ChildPathAny { + return &Parent_ChildPathAny{ + NodePath: ygot.NewNodePath( + []string{"child"}, + map[string]interface{}{}, + n, + ), + } +} diff --git a/ypathgen/testdata/structs/openconfig-simple-31.path-txt b/ypathgen/testdata/structs/openconfig-simple-31.path-txt index 945f05233..7ec3f3dab 100644 --- a/ypathgen/testdata/structs/openconfig-simple-31.path-txt +++ b/ypathgen/testdata/structs/openconfig-simple-31.path-txt @@ -14,32 +14,180 @@ import ( "github.com/openconfig/ygot/ygot" ) -// ParentPath represents the /openconfig-simple/parent YANG schema element. -type ParentPath struct { +// Parent_ChildPath represents the /openconfig-simple/parent/child YANG schema element. +type Parent_ChildPath struct { *ygot.NodePath } -// ParentPathAny represents the wildcard version of the /openconfig-simple/parent YANG schema element. -type ParentPathAny struct { +// Parent_ChildPathAny represents the wildcard version of the /openconfig-simple/parent/child YANG schema element. +type Parent_ChildPathAny struct { *ygot.NodePath } -// Child returns from ParentPath the path struct for its child "child". -func (n *ParentPath) Child() *Parent_ChildPath { - return &Parent_ChildPath{ +// Parent_Child_FourPath represents the /openconfig-simple/parent/child/state/four YANG schema element. +type Parent_Child_FourPath struct { + *ygot.NodePath +} + +// Parent_Child_FourPathAny represents the wildcard version of the /openconfig-simple/parent/child/state/four YANG schema element. +type Parent_Child_FourPathAny struct { + *ygot.NodePath +} + +// Parent_Child_OnePath represents the /openconfig-simple/parent/child/state/one YANG schema element. +type Parent_Child_OnePath struct { + *ygot.NodePath +} + +// Parent_Child_OnePathAny represents the wildcard version of the /openconfig-simple/parent/child/state/one YANG schema element. +type Parent_Child_OnePathAny struct { + *ygot.NodePath +} + +// Parent_Child_ThreePath represents the /openconfig-simple/parent/child/state/three YANG schema element. +type Parent_Child_ThreePath struct { + *ygot.NodePath +} + +// Parent_Child_ThreePathAny represents the wildcard version of the /openconfig-simple/parent/child/state/three YANG schema element. +type Parent_Child_ThreePathAny struct { + *ygot.NodePath +} + +// Parent_Child_TwoPath represents the /openconfig-simple/parent/child/state/two YANG schema element. +type Parent_Child_TwoPath struct { + *ygot.NodePath +} + +// Parent_Child_TwoPathAny represents the wildcard version of the /openconfig-simple/parent/child/state/two YANG schema element. +type Parent_Child_TwoPathAny struct { + *ygot.NodePath +} + +// Four returns from Parent_ChildPath the path struct for its child "four". +func (n *Parent_ChildPath) Four() *Parent_Child_FourPath { + return &Parent_Child_FourPath{ + NodePath: ygot.NewNodePath( + []string{"state", "four"}, + map[string]interface{}{}, + n, + ), + } +} + +// Four returns from Parent_ChildPathAny the path struct for its child "four". +func (n *Parent_ChildPathAny) Four() *Parent_Child_FourPathAny { + return &Parent_Child_FourPathAny{ + NodePath: ygot.NewNodePath( + []string{"state", "four"}, + map[string]interface{}{}, + n, + ), + } +} + +// One returns from Parent_ChildPath the path struct for its child "one". +func (n *Parent_ChildPath) One() *Parent_Child_OnePath { + return &Parent_Child_OnePath{ + NodePath: ygot.NewNodePath( + []string{"state", "one"}, + map[string]interface{}{}, + n, + ), + } +} + +// One returns from Parent_ChildPathAny the path struct for its child "one". +func (n *Parent_ChildPathAny) One() *Parent_Child_OnePathAny { + return &Parent_Child_OnePathAny{ + NodePath: ygot.NewNodePath( + []string{"state", "one"}, + map[string]interface{}{}, + n, + ), + } +} + +// Three returns from Parent_ChildPath the path struct for its child "three". +func (n *Parent_ChildPath) Three() *Parent_Child_ThreePath { + return &Parent_Child_ThreePath{ + NodePath: ygot.NewNodePath( + []string{"state", "three"}, + map[string]interface{}{}, + n, + ), + } +} + +// Three returns from Parent_ChildPathAny the path struct for its child "three". +func (n *Parent_ChildPathAny) Three() *Parent_Child_ThreePathAny { + return &Parent_Child_ThreePathAny{ + NodePath: ygot.NewNodePath( + []string{"state", "three"}, + map[string]interface{}{}, + n, + ), + } +} + +// Two returns from Parent_ChildPath the path struct for its child "two". +func (n *Parent_ChildPath) Two() *Parent_Child_TwoPath { + return &Parent_Child_TwoPath{ + NodePath: ygot.NewNodePath( + []string{"state", "two"}, + map[string]interface{}{}, + n, + ), + } +} + +// Two returns from Parent_ChildPathAny the path struct for its child "two". +func (n *Parent_ChildPathAny) Two() *Parent_Child_TwoPathAny { + return &Parent_Child_TwoPathAny{ + NodePath: ygot.NewNodePath( + []string{"state", "two"}, + map[string]interface{}{}, + n, + ), + } +} + +// RemoteContainerPath represents the /openconfig-simple/remote-container YANG schema element. +type RemoteContainerPath struct { + *ygot.NodePath +} + +// RemoteContainerPathAny represents the wildcard version of the /openconfig-simple/remote-container YANG schema element. +type RemoteContainerPathAny struct { + *ygot.NodePath +} + +// RemoteContainer_ALeafPath represents the /openconfig-simple/remote-container/state/a-leaf YANG schema element. +type RemoteContainer_ALeafPath struct { + *ygot.NodePath +} + +// RemoteContainer_ALeafPathAny represents the wildcard version of the /openconfig-simple/remote-container/state/a-leaf YANG schema element. +type RemoteContainer_ALeafPathAny struct { + *ygot.NodePath +} + +// ALeaf returns from RemoteContainerPath the path struct for its child "a-leaf". +func (n *RemoteContainerPath) ALeaf() *RemoteContainer_ALeafPath { + return &RemoteContainer_ALeafPath{ NodePath: ygot.NewNodePath( - []string{"child"}, + []string{"state", "a-leaf"}, map[string]interface{}{}, n, ), } } -// Child returns from ParentPathAny the path struct for its child "child". -func (n *ParentPathAny) Child() *Parent_ChildPathAny { - return &Parent_ChildPathAny{ +// ALeaf returns from RemoteContainerPathAny the path struct for its child "a-leaf". +func (n *RemoteContainerPathAny) ALeaf() *RemoteContainer_ALeafPathAny { + return &RemoteContainer_ALeafPathAny{ NodePath: ygot.NewNodePath( - []string{"child"}, + []string{"state", "a-leaf"}, map[string]interface{}{}, n, ), diff --git a/ypathgen/testdata/structs/openconfig-simple-32.path-txt b/ypathgen/testdata/structs/openconfig-simple-32.path-txt index 7ec3f3dab..952b2e184 100644 --- a/ypathgen/testdata/structs/openconfig-simple-32.path-txt +++ b/ypathgen/testdata/structs/openconfig-simple-32.path-txt @@ -13,183 +13,3 @@ package ocpathstructs import ( "github.com/openconfig/ygot/ygot" ) - -// Parent_ChildPath represents the /openconfig-simple/parent/child YANG schema element. -type Parent_ChildPath struct { - *ygot.NodePath -} - -// Parent_ChildPathAny represents the wildcard version of the /openconfig-simple/parent/child YANG schema element. -type Parent_ChildPathAny struct { - *ygot.NodePath -} - -// Parent_Child_FourPath represents the /openconfig-simple/parent/child/state/four YANG schema element. -type Parent_Child_FourPath struct { - *ygot.NodePath -} - -// Parent_Child_FourPathAny represents the wildcard version of the /openconfig-simple/parent/child/state/four YANG schema element. -type Parent_Child_FourPathAny struct { - *ygot.NodePath -} - -// Parent_Child_OnePath represents the /openconfig-simple/parent/child/state/one YANG schema element. -type Parent_Child_OnePath struct { - *ygot.NodePath -} - -// Parent_Child_OnePathAny represents the wildcard version of the /openconfig-simple/parent/child/state/one YANG schema element. -type Parent_Child_OnePathAny struct { - *ygot.NodePath -} - -// Parent_Child_ThreePath represents the /openconfig-simple/parent/child/state/three YANG schema element. -type Parent_Child_ThreePath struct { - *ygot.NodePath -} - -// Parent_Child_ThreePathAny represents the wildcard version of the /openconfig-simple/parent/child/state/three YANG schema element. -type Parent_Child_ThreePathAny struct { - *ygot.NodePath -} - -// Parent_Child_TwoPath represents the /openconfig-simple/parent/child/state/two YANG schema element. -type Parent_Child_TwoPath struct { - *ygot.NodePath -} - -// Parent_Child_TwoPathAny represents the wildcard version of the /openconfig-simple/parent/child/state/two YANG schema element. -type Parent_Child_TwoPathAny struct { - *ygot.NodePath -} - -// Four returns from Parent_ChildPath the path struct for its child "four". -func (n *Parent_ChildPath) Four() *Parent_Child_FourPath { - return &Parent_Child_FourPath{ - NodePath: ygot.NewNodePath( - []string{"state", "four"}, - map[string]interface{}{}, - n, - ), - } -} - -// Four returns from Parent_ChildPathAny the path struct for its child "four". -func (n *Parent_ChildPathAny) Four() *Parent_Child_FourPathAny { - return &Parent_Child_FourPathAny{ - NodePath: ygot.NewNodePath( - []string{"state", "four"}, - map[string]interface{}{}, - n, - ), - } -} - -// One returns from Parent_ChildPath the path struct for its child "one". -func (n *Parent_ChildPath) One() *Parent_Child_OnePath { - return &Parent_Child_OnePath{ - NodePath: ygot.NewNodePath( - []string{"state", "one"}, - map[string]interface{}{}, - n, - ), - } -} - -// One returns from Parent_ChildPathAny the path struct for its child "one". -func (n *Parent_ChildPathAny) One() *Parent_Child_OnePathAny { - return &Parent_Child_OnePathAny{ - NodePath: ygot.NewNodePath( - []string{"state", "one"}, - map[string]interface{}{}, - n, - ), - } -} - -// Three returns from Parent_ChildPath the path struct for its child "three". -func (n *Parent_ChildPath) Three() *Parent_Child_ThreePath { - return &Parent_Child_ThreePath{ - NodePath: ygot.NewNodePath( - []string{"state", "three"}, - map[string]interface{}{}, - n, - ), - } -} - -// Three returns from Parent_ChildPathAny the path struct for its child "three". -func (n *Parent_ChildPathAny) Three() *Parent_Child_ThreePathAny { - return &Parent_Child_ThreePathAny{ - NodePath: ygot.NewNodePath( - []string{"state", "three"}, - map[string]interface{}{}, - n, - ), - } -} - -// Two returns from Parent_ChildPath the path struct for its child "two". -func (n *Parent_ChildPath) Two() *Parent_Child_TwoPath { - return &Parent_Child_TwoPath{ - NodePath: ygot.NewNodePath( - []string{"state", "two"}, - map[string]interface{}{}, - n, - ), - } -} - -// Two returns from Parent_ChildPathAny the path struct for its child "two". -func (n *Parent_ChildPathAny) Two() *Parent_Child_TwoPathAny { - return &Parent_Child_TwoPathAny{ - NodePath: ygot.NewNodePath( - []string{"state", "two"}, - map[string]interface{}{}, - n, - ), - } -} - -// RemoteContainerPath represents the /openconfig-simple/remote-container YANG schema element. -type RemoteContainerPath struct { - *ygot.NodePath -} - -// RemoteContainerPathAny represents the wildcard version of the /openconfig-simple/remote-container YANG schema element. -type RemoteContainerPathAny struct { - *ygot.NodePath -} - -// RemoteContainer_ALeafPath represents the /openconfig-simple/remote-container/state/a-leaf YANG schema element. -type RemoteContainer_ALeafPath struct { - *ygot.NodePath -} - -// RemoteContainer_ALeafPathAny represents the wildcard version of the /openconfig-simple/remote-container/state/a-leaf YANG schema element. -type RemoteContainer_ALeafPathAny struct { - *ygot.NodePath -} - -// ALeaf returns from RemoteContainerPath the path struct for its child "a-leaf". -func (n *RemoteContainerPath) ALeaf() *RemoteContainer_ALeafPath { - return &RemoteContainer_ALeafPath{ - NodePath: ygot.NewNodePath( - []string{"state", "a-leaf"}, - map[string]interface{}{}, - n, - ), - } -} - -// ALeaf returns from RemoteContainerPathAny the path struct for its child "a-leaf". -func (n *RemoteContainerPathAny) ALeaf() *RemoteContainer_ALeafPathAny { - return &RemoteContainer_ALeafPathAny{ - NodePath: ygot.NewNodePath( - []string{"state", "a-leaf"}, - map[string]interface{}{}, - n, - ), - } -}