Skip to content
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

Package Mode: Use aliases when used in source #220

Merged
merged 2 commits into from
Oct 28, 2024

Commits on Oct 24, 2024

  1. Package Mode: Use aliases when used in source

    v0.5.0 included uber-go#207, which replaced reflect mode with package mode.
    One issue with package mode that came up (ref: uber-go#216) was that
    generated mocks for interfaces that referred to alias types
    were referring to the aliases' underlying names instead.
    
    e.g.,
    source:
    ```go
    import "github.com/tikv/client-go/v2/internal/apicodec"
    ...
    type Codec = apicodec.Codec
    
    type Foo interface{
    	Bar() Codec
    }
    ```
    mock:
    ```go
    func (m *MockFoo) Bar() apicodec.Codec { // This is a problem, since apicodec is an internal package.
        // ...
    }
    ```
    
    While technically this problem is solved in Go 1.23 with explicit alias types representation,
    (indeed, if you run mockgen on the example in the linked issue with
    `GODEBUG=gotypesalias=1`, you get the expected behavior)
    since we support the last two versions, we can't bump `go.mod` to 1.23 yet.
    This leaves us with the old behavior, where `go/types` does not track alias types.
    You can tell if an object is an alias, but not a type itself,
    and there is no way to retrieve the object of interest
    at the point where we are recursively parsing method types.
    
    This PR works around this issue (temporarily) by using syntax information
    to find all references to aliases in the source package.
    When we find one, we record it in a mapping of underlying type -> alias name.
    Later, while we parse the type tree, we replace any underlying types
    in the mapping with their alias names.
    
    The unexpected side effect of this is that _all_ references to the underlying type
    in the generated mocks will be replaced with the alias, even if
    the source used the underlying name. This is fine because:
    * If the alias is in the mapping, it was used at least once, which means its accessible.
    * From a type-checking perspective, aliases and their underlying types are equivalent.
    
    With this PR, the mocks get generated correctly now:
    ```go
    func (m *MockFoo) Bar() Codec {
        // ...
    }
    ```
    
    Once we can bump `go.mod` to 1.23, we should definitely remove this,
    since the new type alias type nodes solve this problem automatically.
    JacobOaks committed Oct 24, 2024
    Configuration menu
    Copy the full SHA
    e36794b View commit details
    Browse the repository at this point in the history

Commits on Oct 28, 2024

  1. Configuration menu
    Copy the full SHA
    eb1fdaf View commit details
    Browse the repository at this point in the history