From d0aa30f5510ca4381480188df1311c230f8dd3e1 Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Wed, 2 Jun 2021 12:48:54 +0100 Subject: [PATCH] BodySchema: Introduce (dedicated) HoverURL --- decoder/hover.go | 5 +- decoder/hover_test.go | 138 ++++++++++++++++++++++++++++++++++++++++++ schema/body_schema.go | 8 +++ 3 files changed, 148 insertions(+), 3 deletions(-) diff --git a/decoder/hover.go b/decoder/hover.go index 43d3bd2f..a8c70732 100644 --- a/decoder/hover.go +++ b/decoder/hover.go @@ -163,9 +163,8 @@ func (d *Decoder) hoverContentForLabel(i int, block *hclsyntax.Block, bSchema *s content += "\n\n" + labelSchema.Description.Value } - if bs.DocsLink != nil { - link := bs.DocsLink - u, err := d.docsURL(link.URL, "documentHover") + if bs.HoverURL != "" { + u, err := d.docsURL(bs.HoverURL, "documentHover") if err == nil { content += fmt.Sprintf("\n\n[`%s` on %s](%s)", value, u.Hostname(), u.String()) diff --git a/decoder/hover_test.go b/decoder/hover_test.go index 7bd63462..068baa32 100644 --- a/decoder/hover_test.go +++ b/decoder/hover_test.go @@ -392,3 +392,141 @@ func TestDecoder_HoverAtPos_basic(t *testing.T) { }) } } + +func TestDecoder_HoverAtPos_URL(t *testing.T) { + resourceLabelSchema := []*schema.LabelSchema{ + {Name: "type", IsDepKey: true}, + {Name: "name"}, + } + blockSchema := &schema.BlockSchema{ + Labels: resourceLabelSchema, + Description: lang.Markdown("My special block"), + Body: &schema.BodySchema{ + Attributes: map[string]*schema.AttributeSchema{ + "any_attr": {Expr: schema.LiteralTypeOnly(cty.Number)}, + }, + }, + DependentBody: map[schema.SchemaKey]*schema.BodySchema{ + schema.NewSchemaKey(schema.DependencyKeys{ + Labels: []schema.LabelDependent{ + {Index: 0, Value: "sushi"}, + }, + }): { + Detail: "rice, fish etc.", + HoverURL: "https://en.wikipedia.org/wiki/Sushi", + Description: lang.Markdown("Sushi, the Rolls-Rice of Japanese cuisine"), + }, + schema.NewSchemaKey(schema.DependencyKeys{ + Labels: []schema.LabelDependent{ + {Index: 0, Value: "ramen"}, + }, + }): { + Detail: "noodles, broth etc.", + DocsLink: &schema.DocsLink{ + URL: "https://en.wikipedia.org/wiki/Ramen", + Tooltip: "Ramen docs", + }, + Description: lang.Markdown("Ramen, a Japanese noodle soup"), + }, + }, + } + bodySchema := &schema.BodySchema{ + Blocks: map[string]*schema.BlockSchema{ + "myblock": blockSchema, + }, + } + + testCases := []struct { + name string + cfg string + pos hcl.Pos + expectedData *lang.HoverData + }{ + { + "", + `myblock "sushi" "salmon" { + any_attr = 42 +} +`, + hcl.Pos{ + Line: 1, + Column: 12, + Byte: 11, + }, + &lang.HoverData{ + Content: lang.MarkupContent{ + Value: "`sushi`" + ` rice, fish etc. + +Sushi, the Rolls-Rice of Japanese cuisine + +[` + "`sushi`" + ` on en.wikipedia.org](https://en.wikipedia.org/wiki/Sushi)`, + Kind: lang.MarkdownKind, + }, + Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 9, + Byte: 8, + }, + End: hcl.Pos{ + Line: 1, + Column: 16, + Byte: 15, + }, + }, + }, + }, + { + "", + `myblock "ramen" "tonkotsu" { + any_attr = 42 +} +`, + hcl.Pos{ + Line: 1, + Column: 12, + Byte: 13, + }, + &lang.HoverData{ + Content: lang.MarkupContent{ + Value: "`ramen` noodles, broth etc.\n\nRamen, a Japanese noodle soup", + Kind: lang.MarkdownKind, + }, + Range: hcl.Range{ + Filename: "test.tf", + Start: hcl.Pos{ + Line: 1, + Column: 9, + Byte: 8, + }, + End: hcl.Pos{ + Line: 1, + Column: 16, + Byte: 15, + }, + }, + }, + }, + } + for i, tc := range testCases { + t.Run(fmt.Sprintf("%d-%s", i, tc.name), func(t *testing.T) { + d := NewDecoder() + d.SetSchema(bodySchema) + + f, _ := hclsyntax.ParseConfig([]byte(tc.cfg), "test.tf", hcl.InitialPos) + err := d.LoadFile("test.tf", f) + if err != nil { + t.Fatal(err) + } + + data, err := d.HoverAtPos("test.tf", tc.pos) + if err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(tc.expectedData, data, ctydebug.CmpOptions); diff != "" { + t.Fatalf("hover data mismatch: %s", diff) + } + }) + } +} diff --git a/schema/body_schema.go b/schema/body_schema.go index a0ccce08..cd768e0f 100644 --- a/schema/body_schema.go +++ b/schema/body_schema.go @@ -17,8 +17,15 @@ type BodySchema struct { Detail string Description lang.MarkupContent + // DocsLink represents a link to docs that will be exposed + // as part of LinksInFile() DocsLink *DocsLink + // HoverURL represents a URL that will be appended to the end + // of hover data in HoverAtPos(). This can differ from DocsLink, + // but often will match. + HoverURL string + // TODO: Functions } @@ -78,6 +85,7 @@ func (bs *BodySchema) Copy() *BodySchema { Detail: bs.Detail, Description: bs.Description, AnyAttribute: bs.AnyAttribute.Copy(), + HoverURL: bs.HoverURL, DocsLink: bs.DocsLink.Copy(), }