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

fix: Prevent type parsing to interfere with package name in typescrip… #1942

Merged
merged 1 commit into from
Oct 10, 2022

Conversation

ValentinTrinque
Copy link
Contributor

@ValentinTrinque ValentinTrinque commented Oct 7, 2022

Before that fix:

The method...

func (h *Handler) RespondToInteraction(interaction interactor.Interaction) {}

... would generate...

export function RespondToInteraction(arg1:number):Promise<Error>;

... because the interaction package starts with int and anything starting with int is interpreted as number as defined here:

case
strings.HasPrefix(input, "int"),
strings.HasPrefix(input, "uint"),
strings.HasPrefix(input, "float"):
return "number"

Copy link
Member

@leaanthony leaanthony left a comment

Choose a reason for hiding this comment

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

Nice find and thanks for the PR! We are encouraging everyone to include tests with PRs to alert us to regressions at a later date. Do you think you could add a test to this PR? We have tests defined in v2/internal/binding/generate_test.go.

Thanks 🙏

@ValentinTrinque
Copy link
Contributor Author

Yes, of course, I quickly tried, but testing this part is a not super straight forward. I'll see what I can do

@ValentinTrinque
Copy link
Contributor Author

In the end, that was pretty easy.

…t generation

Before that fix:

The method...

```go
func (h *Handler) RespondToInteraction(interaction interactor.Interaction) {}
```

... would generate...

```ts
export function RespondToInteraction(arg1:number):Promise<Error>;
```

... because the `interaction` package starts with `int` and anything starting with `int` is interpreted as `number`.
@ValentinTrinque
Copy link
Contributor Author

I rebased against master.

Copy link
Member

@leaanthony leaanthony left a comment

Choose a reason for hiding this comment

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

Thanks for this. Added a comment. Thoughts?

b := binding.NewBindings(testLogger, []interface{}{&HandlerTest{}}, []interface{}{}, false)

// then
err := b.GenerateGoBindings(generationDir)
Copy link
Member

Choose a reason for hiding this comment

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

I'm wondering if this would have been easier if we could generate to a map[string]string and use that for testing. This would essentially represent map[filepath]filecontents. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that would have been easier.

I think we could significantly improve the design (and its testability) by splitting the bindings generation into multiple component (with Single Responsibility Principle, in mind).

I already had a look to hit, but wanted to keep this fix refactoring-free.

Here is just my brain dump on the matter.

Basically, the idea would be:

  1. A component that parse the go code and build an AST. That already exist AFAIK.
  2. A component that translate that Go AST into a JS AST
  3. Another component that translate that Go AST into TS AST
  4. A component responsible to write the JS AST as JS code
  5. Another component responsible to write the TS AST as TS code

The binding code would essentially become, as pseudo code:

func main() {
  writer := fileWriter{}

  goAST := GetGoASTFromBoundStructs({}interface{&Handler{}})

  go func() {
    ast := toJavascriptAST(goAST)
    obfuscatedAST := obsfuscateJavascriptAST(ast)
    code := toJavascriptCode(jsAST)
    writer.Write(code, "Handler.js")
  }()

  go func() {
    ast := toTypescriptAST(goAST)
    obfuscatedAST := obsfuscateTypescriptAST(ast)
    code := toTypescriptCode(ast)
    writer.Write(jsCode, "Handler.d.ts")
  }()
}

That example doesn't take into account the model generation, UPX and all the nitty gritty details. It's just to convey the idea.

Such design definitely will add more loop interaction but I believe the testability, extensibility (adding specific processing, features, etc) and ability to replace each component will increase dramatically.

Also, this is just a draft thought as I haven't looked in the details. I think I saw that part of the existing code is used for Wails runtime to call the methods and all, so it really needs more thoughts and design.

I am of course open to critics :)

Copy link
Member

@leaanthony leaanthony left a comment

Choose a reason for hiding this comment

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

Let's look at refactoring separately 👍

@leaanthony leaanthony merged commit 2a20049 into wailsapp:master Oct 10, 2022
@ValentinTrinque ValentinTrinque deleted the fix/binding-generation branch October 10, 2022 15:31
@ValentinTrinque
Copy link
Contributor Author

Thanks @leaanthony !

I opened an issue about the refactoring proposal #1953.

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.

2 participants