Skip to content

TNTP-3729: generator for builtin go types #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

bigbes
Copy link
Collaborator

@bigbes bigbes commented Aug 14, 2025

  • supported optional types are int*, uint*, float*, bytes, string, bool
  • fully redo configuration for golangci-lint
  • simple tests for encoding/decoding roundtrip

No documentation, yet, will be added in separate PR.

Closes TNTP-3729.

@bigbes bigbes force-pushed the bigbes/TNTP-3729-generator-for-builtin-go-types branch from d1b999f to 25d23bb Compare August 14, 2025 15:41
@coveralls
Copy link

coveralls commented Aug 14, 2025

Pull Request Test Coverage Report for Build 16990606909

Details

  • 622 of 992 (62.7%) changed or added relevant lines in 17 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+62.7%) to 62.702%

Changes Missing Coverage Covered Lines Changed/Added Lines %
helpers.go 112 116 96.55%
errors.go 0 6 0.0%
bool.go 34 58 58.62%
bytes.go 34 58 58.62%
float32.go 34 58 58.62%
float64.go 34 58 58.62%
int.go 34 58 58.62%
int16.go 34 58 58.62%
int32.go 34 58 58.62%
int64.go 34 58 58.62%
Totals Coverage Status
Change from base Build 16726999280: 62.7%
Covered Lines: 622
Relevant Lines: 992

💛 - Coveralls

@bigbes bigbes force-pushed the bigbes/TNTP-3729-generator-for-builtin-go-types branch 4 times, most recently from a0c2c38 to b3efea9 Compare August 15, 2025 13:00
* supported optional types are int*, uint*, float*, bytes, string, bool
* fully redo configuration for golangci-lint
* simple tests for encoding/decoding roundtrip

Closes TNTP-3729.
@bigbes bigbes force-pushed the bigbes/TNTP-3729-generator-for-builtin-go-types branch from b3efea9 to 9db06ac Compare August 15, 2025 13:06
@bigbes bigbes marked this pull request as ready for review August 15, 2025 13:08
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a code generator for optional builtin Go types including int*, uint*, float*, bytes, string, and bool. The generator creates consistent optional type wrappers with msgpack encoding/decoding support.

  • Introduces a command-line code generator that produces optional type implementations from templates
  • Generates optional types for all numeric types, string, bytes, and bool with consistent API methods
  • Adds comprehensive test coverage for encoding/decoding roundtrips of all generated types

Reviewed Changes

Copilot reviewed 27 out of 28 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
cmd/generator/generator.go Code generator implementation with template-based type generation
*.go (generated files) Generated optional type implementations for builtin Go types
*_test.go Test files covering encoding/decoding roundtrips for each type
helpers.go Helper functions for msgpack encoding/decoding operations
errors.go Custom error type for decode failures
.golangci.yml Updated linter configuration with comprehensive rule set
go.mod Added dependencies for msgpack, testing, and text processing

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

}

func (o Uint8) MustGet() uint8 {
if o.exists {
Copy link
Preview

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic in MustGet() is inverted. It should panic when the value does NOT exist (!o.exists), not when it exists.

Suggested change
if o.exists {
if !o.exists {

Copilot uses AI. Check for mistakes.

}

func (o Uint64) MustGet() uint64 {
if o.exists {
Copy link
Preview

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic in MustGet() is inverted. It should panic when the value does NOT exist (!o.exists), not when it exists.

Suggested change
if o.exists {
if !o.exists {

Copilot uses AI. Check for mistakes.

}

func (o Uint32) MustGet() uint32 {
if o.exists {
Copy link
Preview

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic in MustGet() is inverted. It should panic when the value does NOT exist (!o.exists), not when it exists.

Suggested change
if o.exists {
if !o.exists {

Copilot uses AI. Check for mistakes.

}

func (o Uint16) MustGet() uint16 {
if o.exists {
Copy link
Preview

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic in MustGet() is inverted. It should panic when the value does NOT exist (!o.exists), not when it exists.

Suggested change
if o.exists {
if !o.exists {

Copilot uses AI. Check for mistakes.

}

func (o Uint) MustGet() uint {
if o.exists {
Copy link
Preview

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic in MustGet() is inverted. It should panic when the value does NOT exist (!o.exists), not when it exists.

Suggested change
if o.exists {
if !o.exists {

Copilot uses AI. Check for mistakes.

}

func (o Float64) MustGet() float64 {
if o.exists {
Copy link
Preview

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic in MustGet() is inverted. It should panic when the value does NOT exist (!o.exists), not when it exists.

Suggested change
if o.exists {
if !o.exists {

Copilot uses AI. Check for mistakes.

}

func (o Float32) MustGet() float32 {
if o.exists {
Copy link
Preview

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic in MustGet() is inverted. It should panic when the value does NOT exist (!o.exists), not when it exists.

Suggested change
if o.exists {
if !o.exists {

Copilot uses AI. Check for mistakes.

}

func (o Bytes) MustGet() []byte {
if o.exists {
Copy link
Preview

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic in MustGet() is inverted. It should panic when the value does NOT exist (!o.exists), not when it exists.

Suggested change
if o.exists {
if !o.exists {

Copilot uses AI. Check for mistakes.

}

func (o Bool) MustGet() bool {
if o.exists {
Copy link
Preview

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic in MustGet() is inverted. It should panic when the value does NOT exist (!o.exists), not when it exists.

Suggested change
if o.exists {
if !o.exists {

Copilot uses AI. Check for mistakes.

}

func (o {{.Name}}) MustGet() {{.Type}} {
if o.exists {
Copy link
Preview

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic in the MustGet() template is inverted. It should panic when the value does NOT exist (!o.exists), not when it exists.

Suggested change
if o.exists {
if !o.exists {

Copilot uses AI. Check for mistakes.

Comment on lines +40 to +43
disable:
- return
- assign-exclusive
- assign-expr
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, add comments: why do we disable the checks? After a while, it's not clear.

Comment on lines +13 to +19
disable:
- dupl
- cyclop
- wsl
- nlreturn
- ireturn
- wrapcheck
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, add comments: why do we disable the checks? After a while, it's not clear.

Comment on lines +21 to +26
exclusions:
rules:
- path-except: cmd/generator/*.go
linters:
- forbidigo
- gochecknoglobals
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here.

@@ -10,6 +10,10 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.

### Added

* Implemented optional types for builtin go types int*, uint*, float*,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See:

https://keepachangelog.com/en/1.0.0/

Suggested change
* Implemented optional types for builtin go types int*, uint*, float*,
- Implemented optional types for builtin go types int*, uint*, float*,

Comment on lines +9 to +31

type Bool struct {
value bool
exists bool
}

func SomeBool(value bool) Bool {
return Bool{
value: value,
exists: true,
}
}

func NoneBool() Bool {
return Bool{
exists: false,
value: zero[bool](),
}
}

func (o Bool) IsSome() bool {
return o.exists
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add comments to the public API methods and types. Despite the fact that it will be generated code and comments generated, but this is a general rule in our repositories.

Suggested change
type Bool struct {
value bool
exists bool
}
func SomeBool(value bool) Bool {
return Bool{
value: value,
exists: true,
}
}
func NoneBool() Bool {
return Bool{
exists: false,
value: zero[bool](),
}
}
func (o Bool) IsSome() bool {
return o.exists
}
// Bool is ...
type Bool struct {
value bool
exists bool
}
// SomeBool returns...
func SomeBool(value bool) Bool {
return Bool{
value: value,
exists: true,
}
}
// NoneBool returns ...
func NoneBool() Bool {
return Bool{
exists: false,
value: zero[bool](),
}
}
// IsSome returns ...
func (o Bool) IsSome() bool {
return o.exists
}


err = generateAndWrite()
if err != nil {
fmt.Println("failed to generate or write code: ", err.Error())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should work fine.

Suggested change
fmt.Println("failed to generate or write code: ", err.Error())
fmt.Println("failed to generate or write code: ", err)

// Check if output directory exists and is directory.
switch fInfo, err := os.Stat(absOutputDirectory); {
case err != nil:
fmt.Println("failed to stat output directory: ", err.Error())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

etc

Suggested change
fmt.Println("failed to stat output directory: ", err.Error())
fmt.Println("failed to stat output directory: ", err)

// Get absolute path for output directory.
absOutputDirectory, err := filepath.Abs(outputDirectory)
if err != nil {
fmt.Printf("failed to get absolute path for output directory (%s): %s\n", outputDirectory, err.Error())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

etc

Suggested change
fmt.Printf("failed to get absolute path for output directory (%s): %s\n", outputDirectory, err.Error())
fmt.Printf("failed to get absolute path for output directory (%s): %s\n", outputDirectory, err)

Comment on lines +21 to +31
func decodeInt(decoder *msgpack.Decoder) (int, error) {
return decoder.DecodeInt()
}

func decodeInt8(decoder *msgpack.Decoder) (int8, error) {
return decoder.DecodeInt8()
}

func decodeInt16(decoder *msgpack.Decoder) (int16, error) {
return decoder.DecodeInt16()
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, add a comment: why do we need such helper functions? It is not obvious. Probably the comment could be placed into the header of the file.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'helpers, utils` etc usually a bad filename. As a result, unrelated functions accumulate in these files. It is a good idea to choose more specific name and split the file into several ones.

It is not critical here, so up to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants