Skip to content

Commit

Permalink
Add function docs formatting support
Browse files Browse the repository at this point in the history
  • Loading branch information
SupunS committed May 27, 2021
1 parent 1c06d00 commit bfcf914
Show file tree
Hide file tree
Showing 21 changed files with 296 additions and 48 deletions.
118 changes: 118 additions & 0 deletions tools/docgen/gen/doc_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ import (
)

const nameSeparator = "_"
const newline = "\n"
const mdFileExt = ".md"
const paramPrefix = "@param "
const returnPrefix = "@return "

const baseTemplate = "base-template"
const compositeFullTemplate = "composite-full-template"
Expand Down Expand Up @@ -318,4 +321,119 @@ var functions = template.FuncMap{
return false
}
},

"formatDoc": formatDocs,

"formatFuncDoc": formatFunctionDocs,
}

func formatDocs(docString string) string {
builder := strings.Builder{}

// Trim leading and trailing empty lines
docString = strings.TrimSpace(docString)

lines := strings.Split(docString, newline)

for i, line := range lines {
formattedLine := strings.TrimSpace(line)
if i > 0 {
builder.WriteString(newline)
}
builder.WriteString(formattedLine)
}

return builder.String()
}

func formatFunctionDocs(docString string) string {
builder := strings.Builder{}
params := make([]string, 0)
isPrevLineEmpty := false
docLines := 0
var returnDoc string

// Trim leading and trailing empty lines
docString = strings.TrimSpace(docString)

lines := strings.Split(docString, newline)

for _, line := range lines {
formattedLine := strings.TrimSpace(line)

if strings.HasPrefix(formattedLine, paramPrefix) {
paramInfo := strings.TrimPrefix(formattedLine, paramPrefix)
colonIndex := strings.IndexByte(paramInfo, ':')

// If colon isn't there, cannot determine the param name.
// Hence treat as a normal doc line.
if colonIndex >= 0 {
paramName := strings.TrimSpace(paramInfo[0:colonIndex])

// If param name is empty, treat as a normal doc line.
if len(paramName) > 0 {
paramDoc := strings.TrimSpace(paramInfo[colonIndex+1:])

var formattedParam string
if len(paramDoc) > 0 {
formattedParam = fmt.Sprintf(" - %s : _%s_", paramName, paramDoc)
} else {
formattedParam = fmt.Sprintf(" - %s", paramName)
}

params = append(params, formattedParam)
continue
}
}
} else if strings.HasPrefix(formattedLine, returnPrefix) {
returnDoc = formattedLine
continue
}

// Ignore the line if its a consecutive blank line.
isLineEmpty := len(formattedLine) == 0
if isPrevLineEmpty && isLineEmpty {
continue
}

if docLines > 0 {
builder.WriteString(newline)
}

builder.WriteString(formattedLine)
isPrevLineEmpty = isLineEmpty
docLines++
}

// Print the parameters
if len(params) > 0 {
if !isPrevLineEmpty {
builder.WriteString(newline)
}

builder.WriteString(newline)
builder.WriteString("Parameters:")

for _, param := range params {
builder.WriteString(newline)
builder.WriteString(param)
}

isPrevLineEmpty = false
}

// Print the return type info
if len(returnDoc) > 0 {
if !isPrevLineEmpty {
builder.WriteString(newline)
}

builder.WriteString(newline)

returnInfo := strings.TrimPrefix(returnDoc, returnPrefix)
returnInfo = strings.TrimSpace(returnInfo)
builder.WriteString(fmt.Sprintf("Returns: %s", returnInfo))
}

return builder.String()
}
2 changes: 1 addition & 1 deletion tools/docgen/gen/templates/composite-full-template
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
```

{{- if .DocString}}
{{ .DocString -}}
{{formatDoc .DocString -}}
{{- end -}}

{{- if hasConformance . -}}
Expand Down
2 changes: 1 addition & 1 deletion tools/docgen/gen/templates/composite-template
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
```

{{- if .DocString}}
{{ .DocString}}
{{formatDoc .DocString}}
{{- end}}

[More...]({{fileName .}})
Expand Down
2 changes: 1 addition & 1 deletion tools/docgen/gen/templates/enum-template
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ enum {{.DeclarationIdentifier}}
```

{{- if .DocString}}
{{ .DocString}}
{{formatDoc .DocString}}
{{- end}}
{{end}}
2 changes: 1 addition & 1 deletion tools/docgen/gen/templates/function-template
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ func {{.DeclarationIdentifier}}(
```

{{- if .DocString}}
{{ .DocString}}
{{formatFuncDoc .DocString}}
{{- end}}
{{end}}
2 changes: 1 addition & 1 deletion tools/docgen/gen/templates/initializer-template
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ func {{.DeclarationIdentifier}}(
{{- if $returnType}}: {{$returnType.Type.String}} {{end}}
```

{{if .DocString}}{{.DocString}}{{end}}
{{if .DocString}}{{formatDoc .DocString}}{{end}}
{{end}}
22 changes: 19 additions & 3 deletions tools/docgen/test/doc_gen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestDocGen(t *testing.T) {
// Don't run this as a test
t.Skip()

content, err := ioutil.ReadFile("samples/sample1.cdc")
content, err := ioutil.ReadFile(path.Join("samples", "sample2.cdc"))
require.NoError(t, err)

err = os.MkdirAll("outputs", os.ModePerm)
Expand All @@ -52,7 +52,7 @@ func TestDocGen(t *testing.T) {
}

func TestDocGenForMultiDeclarationFile(t *testing.T) {
content, err := ioutil.ReadFile("samples/sample1.cdc")
content, err := ioutil.ReadFile(path.Join("samples", "sample1.cdc"))
require.NoError(t, err)

docGen := gen.NewDocGenerator()
Expand All @@ -71,7 +71,7 @@ func TestDocGenForMultiDeclarationFile(t *testing.T) {

func TestDocGenForSingleContractFile(t *testing.T) {

content, err := ioutil.ReadFile("samples/sample2.cdc")
content, err := ioutil.ReadFile(path.Join("samples", "sample2.cdc"))
require.NoError(t, err)

docGen := gen.NewDocGenerator()
Expand Down Expand Up @@ -117,3 +117,19 @@ func TestDocGenErrors(t *testing.T) {
assert.IsType(t, err, &os.PathError{})
})
}

func TestFunctionDocFormatting(t *testing.T) {

content, err := ioutil.ReadFile(path.Join("samples", "sample3.cdc"))
require.NoError(t, err)

docGen := gen.NewDocGenerator()

docFiles, err := docGen.GenerateInMemory(string(content))
require.NoError(t, err)
require.Len(t, docFiles, 1)

expectedContent, err := ioutil.ReadFile(path.Join("outputs", "sample3_output.md"))

assert.Equal(t, string(expectedContent), string(docFiles["index.md"]))
}
2 changes: 1 addition & 1 deletion tools/docgen/test/outputs/Color.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
enum Color: Int8 {
}
```
This is an Enum, with explicit type conformance.
This is an Enum, with explicit type conformance.
2 changes: 1 addition & 1 deletion tools/docgen/test/outputs/Direction.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
enum Direction {
}
```
This is an Enum without type conformance.
This is an Enum without type conformance.
28 changes: 15 additions & 13 deletions tools/docgen/test/outputs/NFT.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ contract NFT
field2: String
}
```
NFT is a dummy non-fungible token contract.

NFT is a dummy non-fungible token contract.
Implemented Interfaces:
- `Token`

Expand All @@ -20,8 +19,8 @@ Implemented Interfaces:
```cadence
func foo(a Int, b String):
```
This is a foo function,
This doesn't have a return type.
This is a foo function,
This doesn't have a return type.

---

Expand All @@ -30,10 +29,13 @@ func foo(a Int, b String):
```cadence
func bar(name String, bytes [Int8]): bool
```
This is a bar function, with a return type
@param name: The name. Must be a string
@param bytes: Content
@returns Validity
This is a bar function, with a return type

Parameters:
- name : _The name. Must be a string_
- bytes : _Content to be validated_

Returns: Validity of the content

---

Expand All @@ -56,9 +58,9 @@ struct SomeStruct {
y: {Int: AnyStruct}
}
```
This is some struct. It has
@field x: a string field
@field y: a map of int and any-struct
This is some struct. It has
@field x: a string field
@field y: a map of int and any-struct

[More...](NFT_SomeStruct.md)

Expand All @@ -72,7 +74,7 @@ enum Direction {
case RIGHT
}
```
This is an Enum without type conformance.
This is an Enum without type conformance.

---
### enum `Color`
Expand All @@ -83,6 +85,6 @@ enum Color: Int8 {
case Blue
}
```
This is an Enum, with explicit type conformance.
This is an Enum, with explicit type conformance.

---
2 changes: 1 addition & 1 deletion tools/docgen/test/outputs/NFT_Color.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
enum Color: Int8 {
}
```
This is an Enum, with explicit type conformance.
This is an Enum, with explicit type conformance.
2 changes: 1 addition & 1 deletion tools/docgen/test/outputs/NFT_Direction.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
enum Direction {
}
```
This is an Enum without type conformance.
This is an Enum without type conformance.
8 changes: 4 additions & 4 deletions tools/docgen/test/outputs/NFT_SomeStruct.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ struct SomeStruct
y: {Int: AnyStruct}
}
```
This is some struct. It has
@field x: a string field
@field y: a map of int and any-struct
This is some struct. It has
@field x: a string field
@field y: a map of int and any-struct

### Initializer

Expand All @@ -31,7 +31,7 @@ struct InnerStruct {
b: String
}
```
This is a nested struct.
This is a nested struct.

[More...](NFT_SomeStruct_InnerStruct.md)

Expand Down
2 changes: 1 addition & 1 deletion tools/docgen/test/outputs/NFT_SomeStruct_InnerStruct.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ struct InnerStruct
b: String
}
```
This is a nested struct.
This is a nested struct.
8 changes: 4 additions & 4 deletions tools/docgen/test/outputs/SomeStruct.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ struct SomeStruct
y: {Int: AnyStruct}
}
```
This is some struct. It has
@field x: a string field
@field y: a map of int and any-struct
This is some struct. It has
@field x: a string field
@field y: a map of int and any-struct
Implemented Interfaces:
- `SomeInterface`

Expand All @@ -34,7 +34,7 @@ struct InnerStruct {
b: String
}
```
This is a nested struct.
This is a nested struct.

[More...](SomeStruct_InnerStruct.md)

Expand Down
2 changes: 1 addition & 1 deletion tools/docgen/test/outputs/SomeStruct_InnerStruct.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ struct InnerStruct
b: String
}
```
This is a nested struct.
This is a nested struct.
Loading

0 comments on commit bfcf914

Please sign in to comment.