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 inline comments #96

Merged
merged 4 commits into from
Apr 11, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ func TestGenerateWithImports(t *testing.T) {
ToDo: map[string]string{
"imports/oneref_verbose": "Figure out how to disambiguate struct literals from the struct-with-braces-and-one-element case",
"imports/struct_shorthand": "Shorthand struct notation is currently unsupported, needs fixing",
"imports/inline_comments": "Inline comments do not appear be retrievable from cue.Value.Doc()",
},
}

Expand Down
32 changes: 17 additions & 15 deletions generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,6 @@ type KV struct {
// if memberNames is absent, then keys implicitly generated as CamelCase
// - string struct: struct keys get enum keys, struct values enum values
func (g *generator) genEnum(name string, v cue.Value) []ts.Decl {
vdoc := v.Doc()
// FIXME compensate for attribute-applying call to Unify() on incoming Value
op, dvals := v.Expr()
if op == cue.AndOp {
Expand All @@ -302,7 +301,7 @@ func (g *generator) genEnum(name string, v cue.Value) []ts.Decl {
ret[0] = tsast.TypeDecl{
Name: ts.Ident(name),
Type: tsast.EnumType{Elems: exprs},
CommentList: commentsForGroup(vdoc, true),
CommentList: commentsFor(v, true),
Export: g.c.Export,
}

Expand Down Expand Up @@ -1433,20 +1432,23 @@ func referenceValueAs(v cue.Value, kinds ...TSType) (ts.Expr, error) {
return nil, nil
}

func commentsForGroup(cgs []*ast.CommentGroup, jsdoc bool) []tsast.Comment {
if cgs == nil {
return nil
}
ret := make([]tsast.Comment, 0, len(cgs))
for _, cg := range cgs {
if cg.Line {
panic("hit it")
func commentsFor(v cue.Value, jsdoc bool) []tsast.Comment {
docs := v.Doc()
if s, ok := v.Source().(*ast.Field); ok {
for _, c := range s.Comments() {
if !c.Doc && c.Line {
docs = append(docs, c)
}
}
ret = append(ret, ts.CommentFromCUEGroup(cg, jsdoc))
}
return ret
}

func commentsFor(v cue.Value, jsdoc bool) []tsast.Comment {
return commentsForGroup(v.Doc(), jsdoc)
ret := make([]tsast.Comment, 0, len(docs))
for _, cg := range docs {
ret = append(ret, ts.CommentFromCUEGroup(ts.Comment{
Text: cg.Text(),
Multiline: cg.Doc && !cg.Line,
JSDoc: jsdoc,
}))
}
return ret
}
4 changes: 2 additions & 2 deletions testdata/imports/inline_comments.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ export type Nested = {
* tripleInner has a before comment and
* it's multiline
*/
tripleInner: string,
tripleInner: string; // tripleInner has an inline comment
},
},
}; // Nested has an inline comment

export type SimpleOnlyInline = string; // comment on SimpleOnlyInline
export type SimpleOnlyInline = string; // comment on SimpleOnlyInline
19 changes: 17 additions & 2 deletions ts/ast/lit.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,20 @@ func (o ObjectLit) innerString(aeol EOL, lvl int) string {

write("{\n")
for _, e := range o.Elems {
hasInlineComments := false
for _, c := range e.Comments() {
if c.Pos == CommentInline {
hasInlineComments = true
}
}
indent(lvl)
write(formatInner(aeol, lvl, e))
write(eol)
if hasInlineComments {
write("\n")
} else {
write(eol)
}

}

indent(lvl - 1)
Expand Down Expand Up @@ -97,7 +108,11 @@ func formatInner(eol EOL, lvl int, n Node) string {
b.WriteString(prinner(eol, lvl, n))

for ; i < len(comms) && comms[i].Pos == CommentInline; i++ {
b.WriteString(" " + comms[i].innerString(eol, lvl) + " ")
if _, ok := n.(KeyValueExpr); ok {
b.WriteString("; " + comms[i].innerString(eol, lvl))
} else {
b.WriteString(" " + comms[i].innerString(eol, lvl))
}
}

for ; i < len(comms); i++ {
Expand Down
92 changes: 92 additions & 0 deletions ts/comments.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package ts

import (
"bufio"
"strings"

"github.com/grafana/cuetsy/ts/ast"
"github.com/kr/text"
)

// CommentFromString takes a string input and formats it as an ast.CommentList.
//
// Line breaks are automatically inserted to minimize raggedness, with a loose
// width limit the provided lim.
//
// If the jsdoc param is true, the resulting comment will be formatted with
// JSDoc ( /** ... */ )-style. Otherwise, ordinary comment leader ( // ... ) will
// be used.
//
// The returned ast.CommentList will have the default CommentAbove position.
func CommentFromString(s string, lim int, jsdoc bool) ast.Comment {
var b strings.Builder
prefix := func() { b.WriteString("// ") }
if jsdoc {
b.WriteString("/**\n")
prefix = func() { b.WriteString(" * ") }
}

scanner := bufio.NewScanner(strings.NewReader(text.Wrap(s, lim)))
var i int
for scanner.Scan() {
if i != 0 {
b.WriteString("\n")
}
prefix()
b.WriteString(scanner.Text())
i++
}
if jsdoc {
b.WriteString("\n */\n")
}

return ast.Comment{
Text: b.String(),
}
}

type Comment struct {
Text string
Multiline bool
JSDoc bool
}

// CommentFromCUEGroup creates an ast.CommentList from a Comment.
//
// Original line breaks are preserved, in keeping with principles of semantic line breaks.
func CommentFromCUEGroup(cg Comment) ast.Comment {
var b strings.Builder
pos := ast.CommentAbove
if !cg.Multiline {
pos = ast.CommentInline
}

prefix := func() { b.WriteString("// ") }
if cg.JSDoc && cg.Multiline {
b.WriteString("/**\n")
prefix = func() { b.WriteString(" * ") }
} else {
b.WriteString("//")
prefix = func() { b.WriteString(" ") }
}

scanner := bufio.NewScanner(strings.NewReader(cg.Text))
var i int
for scanner.Scan() {
if i != 0 {
b.WriteString("\n")
}
prefix()
b.WriteString(scanner.Text())
i++
}
if cg.JSDoc && cg.Multiline {
b.WriteString("\n")
b.WriteString(" */")
}

return ast.Comment{
Text: b.String(),
Pos: pos,
}
}
86 changes: 0 additions & 86 deletions ts/ts.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package ts

import (
"bufio"
"strings"

cast "cuelang.org/go/cue/ast"
"github.com/grafana/cuetsy/ts/ast"
"github.com/kr/text"
)

type (
Expand Down Expand Up @@ -98,84 +93,3 @@ func Bool(b bool) Expr {
}
return Ident("false")
}

// CommentFromString takes a string input and formats it as an ast.CommentList.
//
// Line breaks are automatically inserted to minimize raggedness, with a loose
// width limit the provided lim.
//
// If the jsdoc param is true, the resulting comment will be formatted with
// JSDoc ( /** ... */ )-style. Otherwise, ordinary comment leader ( // ... ) will
// be used.
//
// The returned ast.CommentList will have the default CommentAbove position.
func CommentFromString(s string, lim int, jsdoc bool) ast.Comment {
var b strings.Builder
prefix := func() { b.WriteString("// ") }
if jsdoc {
b.WriteString("/**\n")
prefix = func() { b.WriteString(" * ") }
}

scanner := bufio.NewScanner(strings.NewReader(text.Wrap(s, lim)))
var i int
for scanner.Scan() {
if i != 0 {
b.WriteString("\n")
}
prefix()
b.WriteString(scanner.Text())
i++
}
if jsdoc {
b.WriteString("\n */\n")
}

return ast.Comment{
Text: b.String(),
}
}

// CommentFromCUEGroup creates an ast.CommentList from a CUE AST CommentGroup.
//
// Original line breaks are preserved, in keeping with principles of semantic line breaks.
func CommentFromCUEGroup(cg *cast.CommentGroup, jsdoc bool) ast.Comment {
var b strings.Builder
pos := ast.CommentAbove
if cg.Line {
pos = ast.CommentInline
}

prefix := func() { b.WriteString("// ") }
if jsdoc {
b.WriteString("/**")
if cg.Line {
prefix = func() { b.WriteString(" ") }
} else {
b.WriteString("\n")
prefix = func() { b.WriteString(" * ") }
}
}

scanner := bufio.NewScanner(strings.NewReader(cg.Text()))
var i int
for scanner.Scan() {
if i != 0 {
b.WriteString("\n")
}
prefix()
b.WriteString(scanner.Text())
i++
}
if jsdoc {
if !cg.Line {
b.WriteString("\n")
}
b.WriteString(" */")
}

return ast.Comment{
Text: b.String(),
Pos: pos,
}
}