Fix csharp and nodejs doc links generated by resource docs generator (#4237)
* Decode the C# language info from the schema package and set it in the dotnet lang helper for docs. Pass the qualifier for C# property type strings based on whether it is an input or an output property. * Don't pass a module name for Pulumi core types used in TS constructor and Function params. * Add tests for generating doc links for nodejs types. * Add test for confirming input doc link for C# type. * Fix the C# type name for InvokeOptions.
This commit is contained in:
parent
e6be38e285
commit
bdc12b2c98
|
@ -263,7 +263,13 @@ func (mod *modContext) typeString(t schema.Type, lang string, characteristics pr
|
|||
var parts []string
|
||||
var displayName string
|
||||
if lang == "csharp" {
|
||||
csharpNS := fmt.Sprintf("Pulumi.%s.%s.", strings.Title(mod.pkg.Name), strings.Title(mod.mod))
|
||||
// C# types can be wrapped in enumerable types such as List<> or Dictionary<>, so we have to
|
||||
// only replace the namespace string within the < and the >.
|
||||
qualifier := "Inputs"
|
||||
if !characteristics.input {
|
||||
qualifier = "Outputs"
|
||||
}
|
||||
csharpNS := fmt.Sprintf("Pulumi.%s.%s.%s.", strings.Title(mod.pkg.Name), strings.Title(mod.mod), qualifier)
|
||||
displayName = strings.ReplaceAll(langTypeString, csharpNS, "")
|
||||
} else {
|
||||
parts = strings.Split(langTypeString, ".")
|
||||
|
@ -272,7 +278,7 @@ func (mod *modContext) typeString(t schema.Type, lang string, characteristics pr
|
|||
|
||||
// If word-breaks need to be inserted, then the type string
|
||||
// should be html-encoded first if the language is C# in order
|
||||
// to avoid confusing the Hugo rendering where the word-break
|
||||
// to avoid confusing the Hugo rendering where the word-break
|
||||
// tags are inserted.
|
||||
if insertWordBreaks {
|
||||
if lang == "csharp" {
|
||||
|
@ -317,7 +323,7 @@ func (mod *modContext) genConstructorTS(r *schema.Resource, argsOptional bool) [
|
|||
OptionalFlag: "?",
|
||||
Type: propertyType{
|
||||
Name: "pulumi.CustomResourceOptions",
|
||||
Link: docLangHelper.GetDocLinkForResourceType("pulumi", "pulumi", "CustomResourceOptions"),
|
||||
Link: docLangHelper.GetDocLinkForResourceType("pulumi", "", "CustomResourceOptions"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -1076,6 +1082,15 @@ func (mod *modContext) genIndex(exports []string) string {
|
|||
return w.String()
|
||||
}
|
||||
|
||||
func decodeLangSpecificInfo(pkg *schema.Package, lang string, obj interface{}) error {
|
||||
if csharp, ok := pkg.Language[lang]; ok {
|
||||
if err := json.Unmarshal([]byte(csharp), &obj); err != nil {
|
||||
return errors.Wrap(err, "decoding csharp package info")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateModulesFromSchemaPackage(tool string, pkg *schema.Package) map[string]*modContext {
|
||||
// Group resources, types, and functions into modules.
|
||||
modules := map[string]*modContext{}
|
||||
|
@ -1105,17 +1120,24 @@ func generateModulesFromSchemaPackage(tool string, pkg *schema.Package) map[stri
|
|||
return mod
|
||||
}
|
||||
|
||||
goLangHelper := getLanguageDocHelper("go").(*go_gen.DocLanguageHelper)
|
||||
// Decode Go-specific language info.
|
||||
var goInfo go_gen.GoInfo
|
||||
if golang, ok := pkg.Language["go"]; ok {
|
||||
if err := json.Unmarshal(golang, &goInfo); err != nil {
|
||||
panic(fmt.Errorf("decoding go package info: %v", err))
|
||||
}
|
||||
if err := decodeLangSpecificInfo(pkg, "go", &goInfo); err != nil {
|
||||
panic(errors.Wrap(err, "error decoding go language info"))
|
||||
}
|
||||
goLangHelper := getLanguageDocHelper("go").(*go_gen.DocLanguageHelper)
|
||||
// Generate the Go package map info now, so we can use that to get the type string
|
||||
// names later.
|
||||
goLangHelper.GeneratePackagesMap(pkg, tool, goInfo)
|
||||
|
||||
// Decode C#-specific language info.
|
||||
var csharpInfo dotnet.CSharpPackageInfo
|
||||
if err := decodeLangSpecificInfo(pkg, "csharp", &csharpInfo); err != nil {
|
||||
panic(errors.Wrap(err, "error decoding c# language info"))
|
||||
}
|
||||
csharpLangHelper := getLanguageDocHelper("csharp").(*dotnet.DocLanguageHelper)
|
||||
csharpLangHelper.Namespaces = csharpInfo.Namespaces
|
||||
|
||||
pyLangHelper := getLanguageDocHelper("python").(*python.DocLanguageHelper)
|
||||
types := &modContext{pkg: pkg, mod: "types", tool: tool}
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ func (mod *modContext) genFunctionTS(f *schema.Function, resourceName string) []
|
|||
OptionalFlag: "?",
|
||||
Type: propertyType{
|
||||
Name: "pulumi.InvokeOptions",
|
||||
Link: docLangHelper.GetDocLinkForResourceType("pulumi", "pulumi", "InvokeOptions"),
|
||||
Link: docLangHelper.GetDocLinkForResourceType("pulumi", "", "InvokeOptions"),
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -193,13 +193,14 @@ func (mod *modContext) genFunctionCS(f *schema.Function, resourceName string) []
|
|||
})
|
||||
}
|
||||
|
||||
optsType := "Pulumi.InvokeOptions"
|
||||
params = append(params, formalParam{
|
||||
Name: "opts",
|
||||
OptionalFlag: "?",
|
||||
DefaultValue: " = null",
|
||||
Type: propertyType{
|
||||
Name: "InvokeOptions",
|
||||
Link: docLangHelper.GetDocLinkForResourceType("", "", "InvokeOptions"),
|
||||
Name: optsType,
|
||||
Link: docLangHelper.GetDocLinkForResourceType("", "", optsType),
|
||||
},
|
||||
})
|
||||
return params
|
||||
|
|
|
@ -24,7 +24,12 @@ import (
|
|||
)
|
||||
|
||||
// DocLanguageHelper is the DotNet-specific implementation of the DocLanguageHelper.
|
||||
type DocLanguageHelper struct{}
|
||||
type DocLanguageHelper struct {
|
||||
// Namespaces is a map of Pulumi schema module names to their
|
||||
// C# equivalent names, to be used when creating fully-qualified
|
||||
// property type strings.
|
||||
Namespaces map[string]string
|
||||
}
|
||||
|
||||
var _ codegen.DocLanguageHelper = DocLanguageHelper{}
|
||||
|
||||
|
@ -53,9 +58,15 @@ func (d DocLanguageHelper) GetLanguageTypeString(pkg *schema.Package, moduleName
|
|||
typeDetails := map[*schema.ObjectType]*typeDetails{}
|
||||
mod := &modContext{
|
||||
pkg: pkg,
|
||||
mod: moduleName,
|
||||
typeDetails: typeDetails,
|
||||
namespaces: d.Namespaces,
|
||||
}
|
||||
return mod.typeString(t, "", input, false /*state*/, false /*wrapInput*/, true /*requireInitializers*/, optional)
|
||||
qualifier := "Inputs"
|
||||
if !input {
|
||||
qualifier = "Outputs"
|
||||
}
|
||||
return mod.typeString(t, qualifier, input, false /*state*/, false /*wrapInput*/, true /*requireInitializers*/, optional)
|
||||
}
|
||||
|
||||
// GetResourceFunctionResultName returns the name of the result type when a function is used to lookup
|
||||
|
|
81
pkg/codegen/dotnet/doc_test.go
Normal file
81
pkg/codegen/dotnet/doc_test.go
Normal file
|
@ -0,0 +1,81 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// nolint: lll
|
||||
package dotnet
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/codegen/schema"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var testPackageSpec = schema.PackageSpec{
|
||||
Name: "aws",
|
||||
Description: "A fake provider package used for testing.",
|
||||
Meta: &schema.MetadataSpec{
|
||||
ModuleFormat: "(.*)(?:/[^/]*)",
|
||||
},
|
||||
Types: map[string]schema.ObjectTypeSpec{
|
||||
"aws:s3/BucketCorsRule:BucketCorsRule": {
|
||||
Description: "The resource options object.",
|
||||
Type: "object",
|
||||
Properties: map[string]schema.PropertySpec{
|
||||
"stringProp": {
|
||||
Description: "A string prop.",
|
||||
TypeSpec: schema.TypeSpec{
|
||||
Type: "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Resources: map[string]schema.ResourceSpec{
|
||||
"aws:s3/bucket:Bucket": {
|
||||
InputProperties: map[string]schema.PropertySpec{
|
||||
"corsRules": {
|
||||
TypeSpec: schema.TypeSpec{
|
||||
Ref: "#/types/aws:s3/BucketCorsRule:BucketCorsRule",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestGetDocLinkForResourceType(t *testing.T) {
|
||||
d := DocLanguageHelper{}
|
||||
expected := "/docs/reference/pkg/dotnet/Pulumi.Aws/Pulumi.Aws.S3.Bucket.html"
|
||||
link := d.GetDocLinkForResourceType("Aws", "doesNotMatter", "Pulumi.Aws.S3.Bucket")
|
||||
assert.Equal(t, expected, link)
|
||||
}
|
||||
|
||||
func TestGetDocLinkForResourceInputOrOutputType(t *testing.T) {
|
||||
pkg, err := schema.ImportSpec(testPackageSpec)
|
||||
assert.NoError(t, err, "could not import the test package spec")
|
||||
|
||||
namespaces := map[string]string{
|
||||
"s3": "S3",
|
||||
}
|
||||
d := DocLanguageHelper{
|
||||
Namespaces: namespaces,
|
||||
}
|
||||
expected := "/docs/reference/pkg/dotnet/Pulumi.Aws/Pulumi.Aws.S3.Inputs.BucketCorsRuleArgs.html"
|
||||
// Generate the type string for the property type and use that to generate the doc link.
|
||||
propertyType := pkg.Resources[0].InputProperties[0].Type
|
||||
typeString := d.GetLanguageTypeString(pkg, "S3", propertyType, true, true)
|
||||
link := d.GetDocLinkForResourceInputOrOutputType("Aws", "doesNotMatter", typeString, true)
|
||||
assert.Equal(t, expected, link)
|
||||
}
|
|
@ -1203,14 +1203,16 @@ func computePropertyNames(props []*schema.Property, names map[*schema.Property]s
|
|||
return nil
|
||||
}
|
||||
|
||||
type csharpPackageInfo struct {
|
||||
// CSharpPackageInfo represents the C# language-specific info at the root
|
||||
// of the schema.
|
||||
type CSharpPackageInfo struct {
|
||||
PackageReferences map[string]string `json:"packageReferences,omitempty"`
|
||||
Namespaces map[string]string `json:"namespaces,omitempty"`
|
||||
}
|
||||
|
||||
func GeneratePackage(tool string, pkg *schema.Package, extraFiles map[string][]byte) (map[string][]byte, error) {
|
||||
// Decode csharp-specific info
|
||||
var info csharpPackageInfo
|
||||
var info CSharpPackageInfo
|
||||
if csharp, ok := pkg.Language["csharp"]; ok {
|
||||
if err := json.Unmarshal([]byte(csharp), &info); err != nil {
|
||||
return nil, errors.Wrap(err, "decoding csharp package info")
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package nodejs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
|
@ -33,11 +34,18 @@ var _ codegen.DocLanguageHelper = DocLanguageHelper{}
|
|||
|
||||
// GetDocLinkForResourceType returns the NodeJS API doc for a type belonging to a resource provider.
|
||||
func (d DocLanguageHelper) GetDocLinkForResourceType(packageName, modName, typeName string) string {
|
||||
if packageName == "" && modName == "" {
|
||||
panic(errors.New("packageName and modName cannot be empty"))
|
||||
}
|
||||
|
||||
var path string
|
||||
if packageName != "" {
|
||||
switch {
|
||||
case packageName != "" && modName != "":
|
||||
path = fmt.Sprintf("%s/%s", packageName, modName)
|
||||
} else {
|
||||
case packageName == "" && modName != "":
|
||||
path = modName
|
||||
case packageName != "" && modName == "":
|
||||
path = packageName
|
||||
}
|
||||
typeName = strings.ReplaceAll(typeName, "?", "")
|
||||
return fmt.Sprintf("/docs/reference/pkg/nodejs/pulumi/%s/#%s", path, typeName)
|
||||
|
|
53
pkg/codegen/nodejs/doc_test.go
Normal file
53
pkg/codegen/nodejs/doc_test.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
// Copyright 2016-2020, Pulumi Corporation.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Pulling out some of the repeated strings tokens into constants would harm readability, so we just ignore the
|
||||
// goconst linter's warning.
|
||||
//
|
||||
// nolint: lll, goconst
|
||||
package nodejs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDocLinkGenerationForPulumiTypes(t *testing.T) {
|
||||
d := DocLanguageHelper{}
|
||||
t.Run("GenerateCustomResourceOptionsLink", func(t *testing.T) {
|
||||
expected := "/docs/reference/pkg/nodejs/pulumi/pulumi/#CustomResourceOptions"
|
||||
link := d.GetDocLinkForResourceType("pulumi", "", "CustomResourceOptions")
|
||||
assert.Equal(t, expected, link)
|
||||
})
|
||||
t.Run("GenerateInvokeOptionsLink", func(t *testing.T) {
|
||||
expected := "/docs/reference/pkg/nodejs/pulumi/pulumi/#InvokeOptions"
|
||||
link := d.GetDocLinkForResourceType("pulumi", "", "InvokeOptions")
|
||||
assert.Equal(t, expected, link)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetDocLinkForResourceType(t *testing.T) {
|
||||
d := DocLanguageHelper{}
|
||||
expected := "/docs/reference/pkg/nodejs/pulumi/aws/s3/#Bucket"
|
||||
link := d.GetDocLinkForResourceType("aws", "s3", "Bucket")
|
||||
assert.Equal(t, expected, link)
|
||||
}
|
||||
|
||||
func TestGetDocLinkForResourceInputOrOutputType(t *testing.T) {
|
||||
d := DocLanguageHelper{}
|
||||
expected := "/docs/reference/pkg/nodejs/pulumi/aws/types/input/#BucketCorsRule"
|
||||
link := d.GetDocLinkForResourceInputOrOutputType("aws", "s3", "BucketCorsRule", true)
|
||||
assert.Equal(t, expected, link)
|
||||
}
|
Loading…
Reference in a new issue