Skip to content

Commit

Permalink
indexer/javascript: parse jsdoc class comments
Browse files Browse the repository at this point in the history
  • Loading branch information
DaivikDave authored and slimsag committed Jun 28, 2022
1 parent 25718e0 commit 418506c
Showing 1 changed file with 126 additions and 57 deletions.
183 changes: 126 additions & 57 deletions doctree/indexer/javascript/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func (i *javascriptIndexer) IndexDir(ctx context.Context, dir string) (*schema.I
className := firstCaptureContentOr(content, captures["class_name"], "")
superClasses := firstCaptureContentOr(content, captures["superclasses"], "")
classDocs := firstCaptureContentOr(content, captures["class_docs"], "\n")
classDocs = sanitizeDocs(classDocs)
classDocs = extractClassDocs(classDocs)

classLabel := schema.Markdown("class " + className + superClasses)
classes := classesByMod[modName]
Expand Down Expand Up @@ -317,80 +317,149 @@ func getFunctions(node *sitter.Node, content []byte, q string, searchKeyPrefix [
return functions, nil
}

func extractFunctionDocs(s string) string {
func extractClassDocs(s string) string {
// JSDoc comments must start with a /**
// sequence in order to be recognized by the JSDoc parser.
// Comments beginning with /*, /***, or more than 3 stars are ignored by Jsdoc Parser.
if strings.HasPrefix(s, "/**") && !strings.HasPrefix(s, "/***") {
comment := []byte(s)
funcDocs := ""
node, err := sitter.ParseCtx(context.Background(), comment, jsdoc.GetLanguage())
if err != nil {
return ""
if !strings.HasPrefix(s, "/**") && strings.HasPrefix(s, "/***") {
return sanitizeDocs(s)
}

comment := []byte(s)
classDocs := ""
node, err := sitter.ParseCtx(context.Background(), comment, jsdoc.GetLanguage())
if err != nil {
return ""
}
query, err := sitter.NewQuery([]byte(`
(document
(description)? @class_description
(tag
(tag_name)? @tag_name
(type)? @identifier_type
(identifier)? @identifier_name
(description)? @identifier_description
)
)*
`), jsdoc.GetLanguage())
if err != nil {
return ""
}

defer query.Close()

cursor := sitter.NewQueryCursor()
defer cursor.Close()
cursor.Exec(query, node)

propertiesSection := ""
for {
match, ok := cursor.NextMatch()
if !ok {
break
}
query, err := sitter.NewQuery([]byte(`
(document
(description)? @func_description
(tag
(tag_name)? @tag_name
(type)? @identifier_type
(identifier)? @identifier_name
(description)? @identifier_description
)
)*
`), jsdoc.GetLanguage())
if err != nil {
return ""
captures := getCaptures(query, match)
classDescription := firstCaptureContentOr(comment, captures["class_description"], "")
classDocs = fmt.Sprintf("%s\n", classDescription)

identifierType := firstCaptureContentOr(comment, captures["identifier_type"], "")
if identifierType != "" {
identifierType = fmt.Sprintf(" (%s)", identifierType)
}
identifierName := firstCaptureContentOr(comment, captures["identifier_name"], "")
identifierDescription := firstCaptureContentOr(comment, captures["identifier_description"], "")
if identifierDescription != "" {
identifierDescription = fmt.Sprintf(": %s", identifierDescription)
}

defer query.Close()
tagName := firstCaptureContentOr(comment, captures["tag_name"], "")
switch tagName {
case "@property":
propertiesSection += fmt.Sprintf("\n\t%s%s%s", identifierName, identifierType, identifierDescription)
}
}

cursor := sitter.NewQueryCursor()
defer cursor.Close()
cursor.Exec(query, node)
if len(propertiesSection) > 0 {
classDocs += fmt.Sprintf("\n Properties:\n%s", propertiesSection)
}

argsSection := ""
returnSection := ""
for {
match, ok := cursor.NextMatch()
if !ok {
break
}
captures := getCaptures(query, match)
funcDescription := firstCaptureContentOr(comment, captures["func_description"], "")
funcDocs = fmt.Sprintf("%s\n", funcDescription)
return classDocs
}

identifierType := firstCaptureContentOr(comment, captures["identifier_type"], "")
if identifierType != "" {
identifierType = fmt.Sprintf(" (%s)", identifierType)
}
identifierName := firstCaptureContentOr(comment, captures["identifier_name"], "")
identifierDescription := firstCaptureContentOr(comment, captures["identifier_description"], "")
if identifierDescription != "" {
identifierDescription = fmt.Sprintf(": %s", identifierDescription)
}
func extractFunctionDocs(s string) string {
// JSDoc comments must start with a /**
// sequence in order to be recognized by the JSDoc parser.
// Comments beginning with /*, /***, or more than 3 stars are ignored by Jsdoc Parser.
if !strings.HasPrefix(s, "/**") && strings.HasPrefix(s, "/***") {
return sanitizeDocs(s)
}

tagName := firstCaptureContentOr(comment, captures["tag_name"], "")
switch tagName {
case "@param":
argsSection += fmt.Sprintf("\n\t%s%s%s", identifierName, identifierType, identifierDescription)
case "@return":
returnSection += fmt.Sprintf("\n\t%s%s%s", identifierName, identifierType, identifierDescription)
}
comment := []byte(s)
funcDocs := ""
node, err := sitter.ParseCtx(context.Background(), comment, jsdoc.GetLanguage())
if err != nil {
return ""
}
query, err := sitter.NewQuery([]byte(`
(document
(description)? @func_description
(tag
(tag_name)? @tag_name
(type)? @identifier_type
(identifier)? @identifier_name
(description)? @identifier_description
)
)*
`), jsdoc.GetLanguage())
if err != nil {
return ""
}

defer query.Close()

cursor := sitter.NewQueryCursor()
defer cursor.Close()
cursor.Exec(query, node)

argsSection := ""
returnSection := ""
for {
match, ok := cursor.NextMatch()
if !ok {
break
}
captures := getCaptures(query, match)
funcDescription := firstCaptureContentOr(comment, captures["func_description"], "")
funcDocs = fmt.Sprintf("%s\n", funcDescription)

if len(argsSection) > 0 {
funcDocs += fmt.Sprintf("\n Arguments:\n%s", argsSection)
identifierType := firstCaptureContentOr(comment, captures["identifier_type"], "")
if identifierType != "" {
identifierType = fmt.Sprintf(" (%s)", identifierType)
}
identifierName := firstCaptureContentOr(comment, captures["identifier_name"], "")
identifierDescription := firstCaptureContentOr(comment, captures["identifier_description"], "")
if identifierDescription != "" {
identifierDescription = fmt.Sprintf(": %s", identifierDescription)
}

if len(returnSection) > 0 {
funcDocs += fmt.Sprintf("\n Returns:\n%s", returnSection)
tagName := firstCaptureContentOr(comment, captures["tag_name"], "")
switch tagName {
case "@param":
argsSection += fmt.Sprintf("\n\t%s%s%s", identifierName, identifierType, identifierDescription)
case "@return":
returnSection += fmt.Sprintf("\n\t%s%s%s", identifierName, identifierType, identifierDescription)
}
}

if len(argsSection) > 0 {
funcDocs += fmt.Sprintf("\n Arguments:\n%s", argsSection)
}

return funcDocs
if len(returnSection) > 0 {
funcDocs += fmt.Sprintf("\n Returns:\n%s", returnSection)
}

return sanitizeDocs(s)
return funcDocs
}

func sanitizeDocs(s string) string {
Expand Down

0 comments on commit 418506c

Please sign in to comment.