From 621109bf58185b2d01b74657144367cd643d47e9 Mon Sep 17 00:00:00 2001 From: Kane Bruce <54819806+csm-kb@users.noreply.github.com> Date: Sat, 16 Nov 2024 20:00:46 -0700 Subject: [PATCH 1/3] fix(go): fix syntax error in generated source for VisitUndiscriminatedUnion by wrapping if statement --- generators/go/internal/generator/model.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/generators/go/internal/generator/model.go b/generators/go/internal/generator/model.go index 615fec5d980..46abaca51dc 100644 --- a/generators/go/internal/generator/model.go +++ b/generators/go/internal/generator/model.go @@ -828,9 +828,9 @@ func (t *typeVisitor) VisitUndiscriminatedUnion(union *ir.UndiscriminatedUnionTy for _, member := range members { field := fmt.Sprintf("%s.%s", receiver, member.field) if member.date != nil && !member.isOptional { - t.writer.P(fmt.Sprintf("if %s.typ == %q || !%s.IsZero() {", receiver, member.field, field)) + t.writer.P(fmt.Sprintf("if (%s.typ == %q || !%s.IsZero()) {", receiver, member.field, field)) } else { - t.writer.P(fmt.Sprintf("if %s.typ == %q || %s != %s {", receiver, member.field, field, member.zeroValue)) + t.writer.P(fmt.Sprintf("if (%s.typ == %q || %s != %s) {", receiver, member.field, field, member.zeroValue)) } if member.isLiteral { // If we have a literal, we need to marshal it directly. @@ -862,9 +862,9 @@ func (t *typeVisitor) VisitUndiscriminatedUnion(union *ir.UndiscriminatedUnionTy for _, member := range members { field := fmt.Sprintf("%s.%s", receiver, member.field) if member.date != nil && !member.isOptional { - t.writer.P(fmt.Sprintf("if %s.typ == %q || !%s.IsZero() {", receiver, member.field, field)) + t.writer.P(fmt.Sprintf("if (%s.typ == %q || !%s.IsZero()) {", receiver, member.field, field)) } else { - t.writer.P(fmt.Sprintf("if %s.typ == %q || %s != %s {", receiver, member.field, field, member.zeroValue)) + t.writer.P(fmt.Sprintf("if (%s.typ == %q || %s != %s) {", receiver, member.field, field, member.zeroValue)) } t.writer.P("return visitor.Visit", strings.Title(member.field), "(", receiver, ".", member.field, ")") t.writer.P("}") From b1362c3b417bdf64db0fd6d189395bf9a0e2517b Mon Sep 17 00:00:00 2001 From: Kane Bruce <54819806+csm-kb@users.noreply.github.com> Date: Sat, 16 Nov 2024 20:02:01 -0700 Subject: [PATCH 2/3] fix(go): add better error wrapping for generator errors + improved parse error surfacing --- .../go/internal/generator/file_writer.go | 20 ++++++- generators/go/internal/generator/generator.go | 54 +++++++++---------- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/generators/go/internal/generator/file_writer.go b/generators/go/internal/generator/file_writer.go index 8175b206738..8a80b629ee2 100644 --- a/generators/go/internal/generator/file_writer.go +++ b/generators/go/internal/generator/file_writer.go @@ -177,7 +177,25 @@ func removeUnusedImports(filename string, buf []byte) ([]byte, error) { fset := token.NewFileSet() f, err := parser.ParseFile(fset, filename, buf, parser.ParseComments) if err != nil { - return nil, fmt.Errorf("failed to parse Go code: %v", err) + badMetadata := strings.Split(err.Error(), ":") + badLine, _ := strconv.Atoi(badMetadata[1]) + badLineCharIdx, _ := strconv.Atoi(badMetadata[2]) + + badSrcLines := strings.Split(string(bytes.ToValidUTF8(buf, []byte{'?'})), "\n") + badSrc := "" + maxLineDigitCount := len(fmt.Sprint(len(badSrcLines))) + for i, line := range badSrcLines { + if i >= badLine-5 && i <= badLine+3 { + if i == badLine-1 { + badSrc += "\n" + } + badSrc += fmt.Sprintf("%"+fmt.Sprint(maxLineDigitCount)+"d: %s\n", i+1, line) + if i == badLine-1 { + badSrc += strings.Repeat(" ", badLineCharIdx+1) + "^\n" + } + } + } + return nil, fmt.Errorf("failed to parse Go code: %w; source:\n=-=\n%s", err, badSrc) } imports := make(map[string]string) diff --git a/generators/go/internal/generator/generator.go b/generators/go/internal/generator/generator.go index aa794b7ce5a..e5a6b688eca 100644 --- a/generators/go/internal/generator/generator.go +++ b/generators/go/internal/generator/generator.go @@ -126,7 +126,7 @@ func New(config *Config, coordinator *coordinator.Client) (*Generator, error) { func (g *Generator) Generate(mode Mode) ([]*File, error) { ir, err := readIR(g.config.IRFilepath) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to read IR: %w", err) } return g.generate(ir, mode) } @@ -192,7 +192,7 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( referencedImportPath := fernFilepathToImportPath(g.config.ImportPath, referencedType.FernFilepath) if typeImportPath != referencedImportPath { return nil, fmt.Errorf( - "%s referneces %s from another package, but a generator import path was not specified", + "%s references %s from another package, but a generator import path was not specified", typeDeclaration.Name.TypeId, referencedType.TypeId, ) @@ -204,7 +204,7 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( rootPackageName := getRootPackageName(ir, g.config.PackageName) cycleInfo, err := cycleInfoFromIR(ir, g.config.ImportPath) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to cycle info from IR: %w", err) } if cycleInfo != nil { for _, leafType := range cycleInfo.LeafTypes { @@ -325,11 +325,11 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( g.config.ModuleConfig, g.config.Version, ); err != nil { - return nil, err + return nil, fmt.Errorf("failed to write request options definition: %w", err) } file, err := writer.File() if err != nil { - return nil, err + return nil, fmt.Errorf("failed to open new writer.File: %w", err) } files = append(files, file) if ir.Environments != nil { @@ -348,11 +348,11 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( ) generatedEnvironment, err = writer.WriteEnvironments(ir.Environments, useCore) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to write environments: %w", err) } file, err = writer.File() if err != nil { - return nil, err + return nil, fmt.Errorf("failed to open new writer.File: %w", err) } files = append(files, file) } @@ -371,11 +371,11 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( ) generatedAuth, err = writer.WriteRequestOptions(ir.Auth, ir.Headers) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to write request options: %w", err) } file, err = writer.File() if err != nil { - return nil, err + return nil, fmt.Errorf("failed to open new writer.File: %w", err) } files = append(files, file) rootClientInstantiation = generatedClientInstantiation( @@ -398,11 +398,11 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( g.coordinator, ) if err := writer.WriteIdempotentRequestOptionsDefinition(ir.IdempotencyHeaders); err != nil { - return nil, err + return nil, fmt.Errorf("failed to write idempotent request options definition: %w", err) } file, err = writer.File() if err != nil { - return nil, err + return nil, fmt.Errorf("failed to open new writer.File: %w", err) } files = append(files, file) fileInfo = fileInfoForIdempotentRequestOptions() @@ -418,11 +418,11 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( g.coordinator, ) if err := writer.WriteIdempotentRequestOptions(ir.IdempotencyHeaders); err != nil { - return nil, err + return nil, fmt.Errorf("failed to write idempotent request options: %w", err) } file, err = writer.File() if err != nil { - return nil, err + return nil, fmt.Errorf("failed to open new writer.File: %w", err) } files = append(files, file) } @@ -441,11 +441,11 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( g.coordinator, ) if err = writer.WriteLegacyClientOptions(ir.Auth, ir.Headers, ir.IdempotencyHeaders); err != nil { - return nil, err + return nil, fmt.Errorf("failed to write legacy client options: %w", err) } file, err = writer.File() if err != nil { - return nil, err + return nil, fmt.Errorf("failed to open new writer.File: %w", err) } files = append(files, file) } @@ -464,11 +464,11 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( ) if g.config.EnableExplicitNull { if err := writer.WriteOptionalHelpers(useCore); err != nil { - return nil, err + return nil, fmt.Errorf("failed to write optional helpers: %w", err) } file, err = writer.File() if err != nil { - return nil, err + return nil, fmt.Errorf("failed to open new writer.File: %w", err) } files = append(files, file) files = append(files, newOptionalFile(g.coordinator)) @@ -497,7 +497,7 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( } clientTestFile, err := newClientTestFile(g.config.ImportPath, g.coordinator) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to create new client test file: %w", err) } files = append(files, clientTestFile) // Generate the error types, if any. @@ -515,12 +515,12 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( ) for _, irError := range irErrors { if err := writer.WriteError(irError); err != nil { - return nil, err + return nil, fmt.Errorf("failed to write error type: %w", err) } } file, err := writer.File() if err != nil { - return nil, err + return nil, fmt.Errorf("failed to open new writer.File: %w", err) } files = append(files, file) } @@ -545,7 +545,7 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( ir.RootPackage.FernFilepath, ) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to generate service: %w", err) } files = append(files, file) @@ -560,7 +560,7 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( rootClientInstantiation, ) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to generate root service without endpoints: %w", err) } files = append(files, file) @@ -597,7 +597,7 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( subpackageToGenerate.OriginalFernFilepath, ) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to generate service without endpoints: %w", err) } files = append(files, file) continue @@ -611,7 +611,7 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( subpackageToGenerate.OriginalFernFilepath, ) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to generate service: %w", err) } files = append(files, file) @@ -622,7 +622,7 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( // Write the snippets, if any. if g.config.SnippetFilepath != "" { if err := maybeWriteSnippets(g.coordinator, generatedRootClient, g.config.SnippetFilepath); err != nil { - return nil, err + return nil, fmt.Errorf("failed to write snippets: %w", err) } } // Finally, generate the go.mod file, if needed. @@ -633,13 +633,13 @@ func (g *Generator) generate(ir *fernir.IntermediateRepresentation, mode Mode) ( requiresGenerics := g.config.EnableExplicitNull || ir.SdkConfig.HasStreamingEndpoints || generatedPagination file, generatedGoVersion, err := NewModFile(g.coordinator, g.config.ModuleConfig, requiresGenerics) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to create new go.mod file: %w", err) } files = append(files, file) if g.config.IncludeReadme && generatedRootClient.Instantiation != nil { if err := g.generateReadme(generatedRootClient, generatedGoVersion); err != nil { - return nil, err + return nil, fmt.Errorf("failed to generate readme: %w", err) } files = append(files, file) } From d62a0096ff32edfefe9453211fa12561e8eae6a6 Mon Sep 17 00:00:00 2001 From: Kane Bruce <54819806+csm-kb@users.noreply.github.com> Date: Sun, 17 Nov 2024 03:47:28 -0700 Subject: [PATCH 3/3] fix(go): ensure print includes the line printout --- generators/go/internal/generator/file_writer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/go/internal/generator/file_writer.go b/generators/go/internal/generator/file_writer.go index 8a80b629ee2..9dbc58b6432 100644 --- a/generators/go/internal/generator/file_writer.go +++ b/generators/go/internal/generator/file_writer.go @@ -191,7 +191,7 @@ func removeUnusedImports(filename string, buf []byte) ([]byte, error) { } badSrc += fmt.Sprintf("%"+fmt.Sprint(maxLineDigitCount)+"d: %s\n", i+1, line) if i == badLine-1 { - badSrc += strings.Repeat(" ", badLineCharIdx+1) + "^\n" + badSrc += strings.Repeat(" ", badLineCharIdx+maxLineDigitCount+1) + "^\n" } } }