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

programgen(go): Handle conflicting names in imported packages #13289

Merged
merged 2 commits into from Jul 25, 2023

Conversation

abhinav
Copy link
Contributor

@abhinav abhinav commented Jun 26, 2023

This fixes how programgen generates import statements
to handle conflicting imports when two imported packages
have the same name, e.g.

github.com/pulumi/pulumi-aws/sdk/v5/go/aws/ecs
github.com/pulumi/pulumi-awsx/sdk/go/awsx/ecs

To do this, we add a fileImporter type that tracks these imports.
It prefers unnamed imports for packages unless one of the following is
true:

  • the name of the package has already been used by another import
  • the name of the package does not match the last component
    of the import path (e.g., example.com/foo-go with package foo).

If the name has already been used by another import,
it attempts the following in-order:

  • Combine the last two path components of the import path
    into an identifier and use that if available.
    e.g., awsxs3 from sdk/go/awsx/s3.
  • Append a number to the package name and increment it
    until an unused name is found.
    e.g. ecs2, ecs3, and so on.

There's a change in how this information is tracked as well.
Previously, this was a pull approach: various calls returned
programImports objects which all got merged together.

This change switches to a push approach:
as code is generated and imports are requested,
they're submitted to the fileImporter which keeps track of them
until the next Reset() call.
The above also has a nice side effect of dropping a parameter.

Another change worth explicitly calling out:
Previously, getModOrAlias partially duplicated some of the logic
implemented in getPulumiImport, and used mod, originalMod
in a non-obvious way.
This generated incorrect imports like the following
(note the two /aws at the end):

github.com/pulumi/pulumi-aws/sdk/v5/go/aws/aws

This change replicates more of the logic of getPulumiImport
(now called addPulumiImport) into this function,
and addresses the discrepancy in codegen caused by mod/originalMod.
The result leaves most existing code unchanged,
except in a couple existing cases where the resulting changes make sense
given the logic for named imports outlined above.

Resolves #11176

Copy link
Contributor Author

abhinav commented Jun 26, 2023

Current dependencies on/for this PR:

This comment was auto-generated by Graphite.

@pulumi-bot
Copy link
Contributor

pulumi-bot commented Jun 26, 2023

Changelog

[uncommitted] (2023-07-25)

Bug Fixes

  • [programgen/go] Fix conflicting imports generated when two imported packages have the same name.
    #13289

@@ -1,13 +1,13 @@
package main

import (
"git.example.org/thirdparty/sdk/go/pkg"
other "git.example.org/thirdparty/sdk/go/pkg"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

note: basename of import path doesn't match package name, so this makes sense

@@ -1,7 +1,7 @@
package main

import (
resourceProperties "git.example.org/pulumi-synthetic/resourceProperties"
"git.example.org/pulumi-synthetic/resourceProperties"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

base name matches package name so named import not necessary

@abhinav
Copy link
Contributor Author

abhinav commented Jun 26, 2023

bors try

bors bot added a commit that referenced this pull request Jun 26, 2023
@abhinav abhinav requested a review from a team June 26, 2023 21:44
@bors
Copy link
Contributor

bors bot commented Jun 26, 2023

try

Build failed:

@abhinav abhinav marked this pull request as ready for review June 26, 2023 22:15
@abhinav
Copy link
Contributor Author

abhinav commented Jun 26, 2023

try

Build failed:

Build is green. Only the merge failed (for obvious reasons).

@abhinav abhinav force-pushed the abhinav/codegen-go-conflicting-imports branch from 69b7263 to 200bb9f Compare June 30, 2023 04:30
@abhinav abhinav force-pushed the abhinav/codegen-go-conflicting-imports branch from 200bb9f to 0492ff9 Compare July 11, 2023 23:56
candidate := strings.Join(parts[len(parts)-2:], "_")

// Just in case, drop common non-identifier characters.
// e.g., "foo-go" -> "foogo"
Copy link
Member

Choose a reason for hiding this comment

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

Do we not need to worry about a path like "go.dev/pkg" here? parts would be 2 ["go.dev", "pkg"] but "." isn't valid in the import name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I think this logic is more fragile than I intended. I'll have it drop any non-identifier symbols and add some more unit tests.

}

// The name is taken. We need a unique unused alias.
// We prefer a simple "$mod_$name" (e.g. "aws_s3", "awsx_s3") for
Copy link
Member

Choose a reason for hiding this comment

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

I think the underscore is probably better here, but I'm cognisant that Go recommends no underscores in package names and I wonder if we should be trying to maintain that here? "awss3"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that sounds better, especially because this generated code is intended to be read and modified by users.

@abhinav abhinav force-pushed the abhinav/codegen-go-conflicting-imports branch from 0492ff9 to cb91c5b Compare July 12, 2023 21:15
@abhinav
Copy link
Contributor Author

abhinav commented Jul 12, 2023

Updated:

  • Prefer "$mod$name" over "$name$num"
  • Guarantee that the preferred name is a valid Go package name

Copy link
Member

@justinvp justinvp left a comment

Choose a reason for hiding this comment

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

LGTM

Adds a minimal reproduction of the duplicate import issues
reported in #11176.
This fixes how programgen generates import statements
to handle conflicting imports when two imported packages
have the same name, e.g.

    github.com/pulumi/pulumi-aws/sdk/v5/go/aws/ecs
    github.com/pulumi/pulumi-awsx/sdk/go/awsx/ecs

To do this, we add a fileImporter type that tracks these imports.
It prefers unnamed imports for packages unless one of the following is
true:

- the name of the package has already been used by another import
- the name of the package does not match the last component
  of the import path (e.g., `example.com/foo-go` with `package foo`).

If the name has already been used by another import,
it attempts the following in-order:

- Combine the last two path components of the import path
  into an identifier and use that if available.
  e.g., `awsxs3` from `sdk/go/awsx/s3`.
- Append a number to the package name and increment it
  until an unused name is found.
  e.g. `ecs2`, `ecs3`, and so on.

There's a change in how this information is tracked as well.
Previously, this was a pull approach: various calls returned
programImports objects which all got merged together.

This change switches to a push approach:
as code is generated and imports are requested,
they're submitted to the fileImporter which keeps track of them
until the next `Reset()` call.
The above also has a nice side effect of dropping a parameter.

Another change worth explicitly calling out:
Previously, getModOrAlias partially duplicated some of the logic
implemented in getPulumiImport, and used `mod`, `originalMod`
in a non-obvious way.
This generated incorrect imports like the following
(note the two `/aws` at the end):

    github.com/pulumi/pulumi-aws/sdk/v5/go/aws/aws

This change replicates more of the logic of getPulumiImport
(now called addPulumiImport) into this function,
and addresses the discrepancy in codegen caused by `mod`/`originalMod`.
The result leaves most existing code unchanged,
except in a couple existing cases where the resulting changes make sense
given the logic for named imports outlined above.

Resolves #11176
@abhinav abhinav force-pushed the abhinav/codegen-go-conflicting-imports branch from cb91c5b to a24ad18 Compare July 25, 2023 19:49
@abhinav
Copy link
Contributor Author

abhinav commented Jul 25, 2023

bors merge

@bors
Copy link
Contributor

bors bot commented Jul 25, 2023

Build succeeded!

The publicly hosted instance of bors-ng is deprecated and will go away soon.

If you want to self-host your own instance, instructions are here.
For more help, visit the forum.

If you want to switch to GitHub's built-in merge queue, visit their help page.

@bors bors bot merged commit e48af89 into master Jul 25, 2023
57 checks passed
@bors bors bot deleted the abhinav/codegen-go-conflicting-imports branch July 25, 2023 21:31
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.

[codegen/go] Conflicting imports are generated
4 participants