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 nodejs external enums #10286

Merged
merged 7 commits into from Jul 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG_PENDING.md
Expand Up @@ -3,4 +3,7 @@
### Bug Fixes

- [sdk/dotnet] Fix serialization of non-generic list types.
[#10277](https://github.com/pulumi/pulumi/pull/10277)
[#10277](https://github.com/pulumi/pulumi/pull/10277)

- [codegen/nodejs] Correctly reference external enums.
[#10286](https://github.com/pulumi/pulumi/pull/10286)
39 changes: 29 additions & 10 deletions pkg/codegen/nodejs/gen.go
Expand Up @@ -214,7 +214,11 @@ func (mod *modContext) objectType(pkg *schema.Package, details *typeDetails, tok
modName, name := namingCtx.tokenToModName(tok), tokenToName(tok)

if enum {
return "enums." + modName + title(name)
prefix := "enums."
if external {
prefix = pkgName
}
return prefix + modName + title(name)
}

if args && input && details != nil && details.usedInFunctionOutputVersionInputs {
Expand Down Expand Up @@ -289,7 +293,7 @@ func (mod *modContext) typeAst(t schema.Type, input bool, constValue interface{}
}
return tstypes.Identifier(fmt.Sprintf("pulumi.Input<%s>", typ))
case *schema.EnumType:
return tstypes.Identifier(mod.objectType(nil, nil, t.Token, input, false, true))
return tstypes.Identifier(mod.objectType(t.Package, nil, t.Token, input, false, true))
case *schema.ArrayType:
return tstypes.Array(mod.typeAst(t.ElementType, input, constValue))
case *schema.MapType:
Expand Down Expand Up @@ -1303,6 +1307,12 @@ func (mod *modContext) getTypeImportsForResource(t schema.Type, recurse bool, ex
case *schema.MapType:
return mod.getTypeImports(t.ElementType, recurse, externalImports, imports, seen)
case *schema.EnumType:
// If the enum is from another package, add an import for the external package.
if t.Package != nil && t.Package != mod.pkg {
pkg := t.Package.Name
writeImports(pkg)
return false
}
return true
case *schema.ObjectType:
// If it's from another package, add an import for the external package.
Expand Down Expand Up @@ -1517,7 +1527,7 @@ func (mod *modContext) sdkImports(nested, utilities bool) []string {

relRoot := mod.getRelativePath()
if nested {
enumsImport := ""
var enumsImport string
containsEnums := mod.pkg.Language["nodejs"].(NodePackageInfo).ContainsEnums
if containsEnums {
enumsImport = ", enums"
Expand Down Expand Up @@ -1621,6 +1631,12 @@ func (mod *modContext) getNamespaces() map[string]*namespace {
func (mod *modContext) genNamespace(w io.Writer, ns *namespace, input bool, level int) error {
indent := strings.Repeat(" ", level)

// We generate the input and output namespaces when there are enums, regardless of if
// they are empty.
if ns == nil {
return nil
}

sort.Slice(ns.types, func(i, j int) bool {
return tokenToName(ns.types[i].Token) < tokenToName(ns.types[j].Token)
})
Expand Down Expand Up @@ -1824,7 +1840,8 @@ func (mod *modContext) gen(fs fs) error {
}

// Nested types
if len(mod.types) > 0 {
// Importing enums always imports inputs and outputs, so if we have enums we generate inputs and outputs
if len(mod.types) > 0 || (mod.pkg.Language["nodejs"].(NodePackageInfo).ContainsEnums && mod.mod == "types") {
input, output, err := mod.genTypes()
if err != nil {
return err
Expand Down Expand Up @@ -1891,6 +1908,10 @@ func (mod *modContext) genIndex(exports []string) string {
if info.ContainsEnums {
if mod.mod == "types" {
children.Add("enums")
// input & output might be empty, but they will be imported with enums, so we
// need to have them.
children.Add("input")
children.Add("output")
} else if len(mod.enums) > 0 {
fmt.Fprintf(w, "\n")
fmt.Fprintf(w, "// Export enums:\n")
Expand Down Expand Up @@ -2027,11 +2048,9 @@ func (mod *modContext) hasEnums() bool {
if len(mod.enums) > 0 {
return true
}
if len(mod.children) > 0 {
for _, mod := range mod.children {
if mod.hasEnums() {
return true
}
for _, mod := range mod.children {
if mod.hasEnums() {
return true
}
}
return false
Expand Down Expand Up @@ -2383,7 +2402,7 @@ func generateModuleContextMap(tool string, pkg *schema.Package, extraFiles map[s
continue
}
}
if len(types.types) > 0 {
if len(types.types) > 0 || info.ContainsEnums {
typeDetails, typeList := types.typeDetails, types.types
types = getMod("types")
types.typeDetails, types.types = typeDetails, typeList
Expand Down
8 changes: 7 additions & 1 deletion pkg/codegen/python/gen.go
Expand Up @@ -565,7 +565,12 @@ func (mod *modContext) isEmpty() bool {
}

func (mod *modContext) submodulesExist() bool {
return len(mod.children) > 0
for _, submod := range mod.children {
if !submod.isEmpty() {
return true
}
}
return false
}

func (mod *modContext) unqualifiedImportName() string {
Expand Down Expand Up @@ -641,6 +646,7 @@ func (mod *modContext) genInit(exports []string) string {
})

fmt.Fprintf(w, "\n# Make subpackages available:\n")

fmt.Fprintf(w, "if typing.TYPE_CHECKING:\n")

for _, submod := range children {
Expand Down
13 changes: 7 additions & 6 deletions pkg/codegen/python/gen_test.go
Expand Up @@ -162,16 +162,17 @@ func buildVirtualEnv(ctx context.Context) error {
return err
}

if !gotSdk {
return fmt.Errorf("This test requires Python SDK to be built; please `cd sdk/python && make ensure build install`")
}

// install Pulumi Python SDK from the current source tree, -e means no-copy, ref directly
pyCmd := python.VirtualEnvCommand(venvDir, "python", "-m", "pip", "install", "-e", sdkDir)
pyCmd.Dir = hereDir
err = pyCmd.Run()
output, err := pyCmd.CombinedOutput()
if err != nil {
contract.Failf("failed to link venv against in-source pulumi: %v", err)
}

if !gotSdk {
return fmt.Errorf("This test requires Python SDK to be built; please `cd sdk/python && make ensure build install`")
contract.Failf("failed to link venv against in-source pulumi: %v\nstdout/stderr:\n%s",
err, output)
}

return nil
Expand Down
10 changes: 7 additions & 3 deletions pkg/codegen/testing/test/sdk_driver.go
Expand Up @@ -198,9 +198,8 @@ var PulumiPulumiSDKTests = []*SDKTest{
Skip: codegen.NewStringSet("go/test", "dotnet/test"),
},
{
Directory: "plain-and-default",
Description: "Ensure that a resource with a plain default property works correctly",
SkipCompileCheck: codegen.NewStringSet(nodejs),
Directory: "plain-and-default",
Description: "Ensure that a resource with a plain default property works correctly",
},
{
Directory: "plain-object-defaults",
Expand Down Expand Up @@ -268,6 +267,11 @@ var PulumiPulumiSDKTests = []*SDKTest{
Directory: "enum-reference",
Description: "Ensure referencing external types/resources with referenced enums import correctly",
},
{
Directory: "external-enum",
Description: "Ensure we generate valid tokens for external enums",
Skip: codegen.NewStringSet("dotnet/any"),
},
{
Directory: "internal-dependencies-go",
Description: "Emit Go internal dependencies",
Expand Down
29 changes: 29 additions & 0 deletions pkg/codegen/testing/test/testdata/external-enum/docs/_index.md
@@ -0,0 +1,29 @@
---
title: "example"
title_tag: "example.example"
meta_desc: ""
layout: api
no_edit_this_page: true
---

<!-- WARNING: this file was generated by test. -->
<!-- Do not edit by hand unless you're certain you know what you are doing! -->



<h2 id="resources">Resources</h2>
<ul class="api">
<li><a href="component" title="Component"><span class="api-symbol api-symbol--resource"></span>Component</a></li>
<li><a href="provider" title="Provider"><span class="api-symbol api-symbol--resource"></span>Provider</a></li>
</ul>

<h2 id="package-details">Package Details</h2>
<dl class="package-details">
<dt>Repository</dt>
<dd><a href=""></a></dd>
<dt>License</dt>
<dd></dd>
<dt>Version</dt>
<dd>0.0.1</dd>
</dl>

@@ -0,0 +1,7 @@
{
"emittedFiles": [
"_index.md",
"component/_index.md",
"provider/_index.md"
]
}