Add ability to have multiple comments

This commit is contained in:
Joey Yakimowich-Payne 2020-04-25 13:08:52 -06:00
commit 6a8d05dae2
2 changed files with 56 additions and 33 deletions

View file

@ -691,7 +691,7 @@ proc newRecListTree(gState: State, name: string, node: TSNode): PNode =
let let
fdecl = node[i].anyChildInTree("field_declaration_list") fdecl = node[i].anyChildInTree("field_declaration_list")
edecl = node[i].anyChildInTree("enumerator_list") edecl = node[i].anyChildInTree("enumerator_list")
commentNode = node[i].getNextCommentNode() commentNodes = node[i].getNextCommentNodes()
# `tname` is name of nested struct / union / enum just # `tname` is name of nested struct / union / enum just
# added, passed on as type name for field in `newIdentDefs()` # added, passed on as type name for field in `newIdentDefs()`
@ -717,7 +717,7 @@ proc newRecListTree(gState: State, name: string, node: TSNode): PNode =
# Add nkIdentDefs for each field # Add nkIdentDefs for each field
for field in gState.newIdentDefs(name, node[i], i, ftname = tname, exported = true): for field in gState.newIdentDefs(name, node[i], i, ftname = tname, exported = true):
if not field.isNil: if not field.isNil:
field.comment = gState.getCommentVal(commentNode) field.comment = gState.getCommentsStr(commentNodes)
result.add field result.add field
proc addTypeObject(gState: State, node: TSNode, typeDef: PNode = nil, fname = "", istype = false, union = false) = proc addTypeObject(gState: State, node: TSNode, typeDef: PNode = nil, fname = "", istype = false, union = false) =
@ -727,7 +727,7 @@ proc addTypeObject(gState: State, node: TSNode, typeDef: PNode = nil, fname = ""
# If `fname` is set, use it as the name when creating new PNode # If `fname` is set, use it as the name when creating new PNode
# If `istype` is set, this is a typedef, else struct/union # If `istype` is set, this is a typedef, else struct/union
decho("addTypeObject()") decho("addTypeObject()")
let commentNode = node.tsNodeParent().getPrevCommentNode() let commentNodes = node.tsNodeParent().getPrevCommentNodes()
let let
# Object has fields or not # Object has fields or not
@ -841,7 +841,7 @@ proc addTypeObject(gState: State, node: TSNode, typeDef: PNode = nil, fname = ""
gState.addPragma(node, typeDef[0][1], pragmas) gState.addPragma(node, typeDef[0][1], pragmas)
# nkTypeSection.add # nkTypeSection.add
typeDef.comment = gState.getCommentVal(commentNode) typeDef.comment = gState.getCommentsStr(commentNodes)
gState.typeSection.add typeDef gState.typeSection.add typeDef
gState.printDebug(typeDef) gState.printDebug(typeDef)
@ -853,7 +853,7 @@ proc addTypeObject(gState: State, node: TSNode, typeDef: PNode = nil, fname = ""
# Current node has fields # Current node has fields
let let
origname = gState.getNodeVal(node.getAtom()) origname = gState.getNodeVal(node.getAtom())
commentNode = node.getNextCommentNode() commentNodes = node.getNextCommentNodes()
# Fix issue #185 # Fix issue #185
name = name =
@ -865,7 +865,7 @@ proc addTypeObject(gState: State, node: TSNode, typeDef: PNode = nil, fname = ""
if name.nBl and gState.identifierNodes.hasKey(name): if name.nBl and gState.identifierNodes.hasKey(name):
let let
def = gState.identifierNodes[name] def = gState.identifierNodes[name]
def.comment = gState.getCommentVal(commentNode) def.comment = gState.getCommentsStr(commentNodes)
# Duplicate nkTypeDef for `name` with empty fields # Duplicate nkTypeDef for `name` with empty fields
if def.kind == nkTypeDef and def.len == 3 and if def.kind == nkTypeDef and def.len == 3 and
@ -898,7 +898,7 @@ proc addTypeTyped(gState: State, node: TSNode, ftname = "", offset = 0) =
decho("addTypeTyped()") decho("addTypeTyped()")
let let
start = getStartAtom(node) start = getStartAtom(node)
commentNode = node.getPrevCommentNode() commentNodes = node.getPrevCommentNodes()
for i in start+1+offset ..< node.len: for i in start+1+offset ..< node.len:
# Add a type of a specific type # Add a type of a specific type
let let
@ -906,7 +906,7 @@ proc addTypeTyped(gState: State, node: TSNode, ftname = "", offset = 0) =
typeDef = gState.newXIdent(node[i], istype = true) typeDef = gState.newXIdent(node[i], istype = true)
if not typeDef.isNil: if not typeDef.isNil:
typeDef.comment = gState.getCommentVal(commentNode) typeDef.comment = gState.getCommentsStr(commentNodes)
let let
name = typeDef.getIdentName() name = typeDef.getIdentName()
@ -1403,7 +1403,7 @@ proc addEnum(gState: State, node: TSNode) =
# nkIdent(name) <- set the comment here # nkIdent(name) <- set the comment here
# ) # )
# ) # )
defineNode[0][1].comment = gState.getCommentVal(node.getPrevCommentNode()) defineNode[0][1].comment = gState.getCommentsStr(node.getPrevCommentNodes())
gState.enumSection.add defineNode gState.enumSection.add defineNode
# Create const for fields # Create const for fields
@ -1411,7 +1411,7 @@ proc addEnum(gState: State, node: TSNode) =
fnames: HashSet[string] fnames: HashSet[string]
# Hold all of field information so that we can add all of them # Hold all of field information so that we can add all of them
# after the const identifiers has been updated # after the const identifiers has been updated
fieldDeclarations: seq[tuple[fname: string, fval: string, cexpr: Option[TSNode], comment: Option[TSNode]]] fieldDeclarations: seq[tuple[fname: string, fval: string, cexpr: Option[TSNode], comment: seq[TSNode]]]
for i in 0 .. enumlist.len - 1: for i in 0 .. enumlist.len - 1:
let let
en = enumlist[i] en = enumlist[i]
@ -1420,7 +1420,7 @@ proc addEnum(gState: State, node: TSNode) =
let let
atom = en.getAtom() atom = en.getAtom()
commentNode = en.getNextCommentNode() commentNodes = en.getNextCommentNodes()
fname = gState.getIdentifier(gState.getNodeVal(atom), nskEnumField) fname = gState.getIdentifier(gState.getNodeVal(atom), nskEnumField)
if fname.nBl and gState.addNewIdentifer(fname): if fname.nBl and gState.addNewIdentifer(fname):
@ -1434,9 +1434,9 @@ proc addEnum(gState: State, node: TSNode) =
fval = &"({prev} + 1).{name}" fval = &"({prev} + 1).{name}"
if en.len > 1 and en[1].getName() in gEnumVals: if en.len > 1 and en[1].getName() in gEnumVals:
fieldDeclarations.add((fname, "", some(en[1]), commentNode)) fieldDeclarations.add((fname, "", some(en[1]), commentNodes))
else: else:
fieldDeclarations.add((fname, fval, none(TSNode), commentNode)) fieldDeclarations.add((fname, fval, none(TSNode), commentNodes))
fnames.incl fname fnames.incl fname
prev = fname prev = fname
@ -1446,20 +1446,20 @@ proc addEnum(gState: State, node: TSNode) =
gState.constIdentifiers.incl fnames gState.constIdentifiers.incl fnames
# parseCExpression requires all const identifiers to be present for the enum # parseCExpression requires all const identifiers to be present for the enum
for (fname, fval, cexprNode, commentNode) in fieldDeclarations: for (fname, fval, cexprNode, commentNodes) in fieldDeclarations:
var fval = fval var fval = fval
if cexprNode.isSome: if cexprNode.isSome:
fval = "(" & $gState.parseCExpression(gState.getNodeVal(cexprNode.get()), name) & ")." & name fval = "(" & $gState.parseCExpression(gState.getNodeVal(cexprNode.get()), name) & ")." & name
# Cannot use newConstDef() since parseString(fval) adds backticks to and/or # Cannot use newConstDef() since parseString(fval) adds backticks to and/or
let constNode = gState.parseString(&"const {fname}* = {fval}")[0][0] let constNode = gState.parseString(&"const {fname}* = {fval}")[0][0]
constNode.comment = gState.getCommentVal(commentNode) constNode.comment = gState.getCommentsStr(commentNodes)
gState.constSection.add constNode gState.constSection.add constNode
# Add other names # Add other names
if node.getName() == "type_definition" and node.len > 1: if node.getName() == "type_definition" and node.len > 1:
gState.addTypeTyped(node, ftname = name, offset = offset) gState.addTypeTyped(node, ftname = name, offset = offset)
proc addProcVar(gState: State, node, rnode: TSNode, commentNode: Option[TSNode]) = proc addProcVar(gState: State, node, rnode: TSNode, commentNodes: seq[TSNode]) =
# Add a proc variable # Add a proc variable
decho("addProcVar()") decho("addProcVar()")
let let
@ -1512,13 +1512,13 @@ proc addProcVar(gState: State, node, rnode: TSNode, commentNode: Option[TSNode])
# nkEmpty() # nkEmpty()
# ) # )
identDefs.comment = gState.getCommentVal(commentNode) identDefs.comment = gState.getCommentsStr(commentNodes)
# nkVarSection.add # nkVarSection.add
gState.varSection.add identDefs gState.varSection.add identDefs
gState.printDebug(identDefs) gState.printDebug(identDefs)
proc addProc(gState: State, node, rnode: TSNode, commentNode: Option[TSNode]) = proc addProc(gState: State, node, rnode: TSNode, commentNodes: seq[TSNode]) =
# Add a proc # Add a proc
# #
# `node` is the `nth` child of (declaration) # `node` is the `nth` child of (declaration)
@ -1624,7 +1624,7 @@ proc addProc(gState: State, node, rnode: TSNode, commentNode: Option[TSNode]) =
procDef.add newNode(nkEmpty) procDef.add newNode(nkEmpty)
procDef.add newNode(nkEmpty) procDef.add newNode(nkEmpty)
procDef.comment = gState.getCommentVal(commentNode) procDef.comment = gState.getCommentsStr(commentNodes)
# nkProcSection.add # nkProcSection.add
gState.procSection.add procDef gState.procSection.add procDef
@ -1636,20 +1636,19 @@ proc addDecl(gState: State, node: TSNode) =
decho("addDecl()") decho("addDecl()")
gState.printDebug(node) gState.printDebug(node)
let let
start = getStartAtom(node) start = getStartAtom(node)
commentNode = node.getPrevCommentNode() commentNodes = node.getPrevCommentNodes()
for i in start+1 ..< node.len: for i in start+1 ..< node.len:
if not node[i].firstChildInTree("function_declarator").isNil: if not node[i].firstChildInTree("function_declarator").isNil:
# Proc declaration - var or actual proc # Proc declaration - var or actual proc
if node[i].getAtom().getPxName(1) == "pointer_declarator": if node[i].getAtom().getPxName(1) == "pointer_declarator":
# proc var # proc var
gState.addProcVar(node[i], node[start], commentNode) gState.addProcVar(node[i], node[start], commentNodes)
else: else:
# proc # proc
gState.addProc(node[i], node[start], commentNode) gState.addProc(node[i], node[start], commentNodes)
else: else:
# Regular var # Regular var
discard discard
@ -1664,11 +1663,11 @@ proc addDef(gState: State, node: TSNode) =
let let
start = getStartAtom(node) start = getStartAtom(node)
commentNode = node.getPrevCommentNode() commentNodes = node.getPrevCommentNodes()
if node[start+1].getName() == "function_declarator": if node[start+1].getName() == "function_declarator":
if gState.isIncludeHeader(): if gState.isIncludeHeader():
gState.addProc(node[start+1], node[start], commentNode) gState.addProc(node[start+1], node[start], commentNodes)
else: else:
gecho &"\n# proc '$1' skipped - static inline procs require 'includeHeader'" % gecho &"\n# proc '$1' skipped - static inline procs require 'includeHeader'" %
gState.getNodeVal(node[start+1].getAtom()) gState.getNodeVal(node[start+1].getAtom())

View file

@ -1,4 +1,5 @@
import dynlib, macros, os, sequtils, sets, strformat, strutils, tables, times, options import dynlib, macros, os, sequtils, sets, strformat, strutils, tables, times, options
import algorithm
import regex import regex
@ -637,12 +638,13 @@ proc getNameKind*(name: string): tuple[name: string, kind: Kind, recursive: bool
if result.kind != exactlyOne: if result.kind != exactlyOne:
result.name = result.name[0 .. ^2] result.name = result.name[0 .. ^2]
proc getCommentVal*(gState: State, commentNode: Option[TSNode]): string = proc getCommentsStr*(gState: State, commentNodes: seq[TSNode]): string =
if commentNode.isSome(): if commentNodes.len > 0:
result = "::\n " & gState.getNodeVal(commentNode.get()).replace(re" *(/\*\*|\*\*/|\*/|\*)", "").replace("\n", "\n ").strip() result = "::"
for commentNode in commentNodes:
result &= "\n " & gState.getNodeVal(commentNode).replace(re" *(//|/\*\*|\*\*/|/\*|\*/|\*)", "").replace("\n", "\n ").strip()
template findComment(procName: untyped): untyped = template findComment(procName: untyped): untyped =
result = none(TSNode)
var sibling = node.`procName`() var sibling = node.`procName`()
var i = 0 var i = 0
while not sibling.isNil and i < maxSearch: while not sibling.isNil and i < maxSearch:
@ -651,11 +653,33 @@ template findComment(procName: untyped): untyped =
sibling = sibling.`procName`() sibling = sibling.`procName`()
i += 1 i += 1
proc getPrevCommentNode*(node: TSNode, maxSearch=1): Option[TSNode] = proc getPrevCommentNodes*(node: TSNode, maxSearch=1): seq[TSNode] =
findComment(tsNodePrevNamedSibling) ## Here we want to go until the node we get is not a comment
## for cases with multiple ``//`` comments instead of one ``/* */``
## section
var sibling = node.tsNodePrevNamedSibling()
var i = 0
while not sibling.isNil and i < maxSearch:
while not sibling.isNil and sibling.getName() == "comment":
result.add(sibling)
sibling = sibling.tsNodePrevNamedSibling()
if sibling.isNil:
result.reverse
return
sibling = sibling.tsNodePrevNamedSibling()
i += 1
proc getNextCommentNode*(node: TSNode, maxSearch=1): Option[TSNode] = result.reverse
findComment(tsNodeNextNamedSibling)
proc getNextCommentNodes*(node: TSNode, maxSearch=1): seq[TSNode] =
## We only want to search for the next comment node (ie: inline)
var sibling = node.tsNodeNextNamedSibling()
var i = 0
while not sibling.isNil and i < maxSearch:
if sibling.getName() == "comment":
return @[sibling]
sibling = sibling.tsNodeNextNamedSibling()
i += 1
proc getTSNodeNamedChildNames*(node: TSNode): seq[string] = proc getTSNodeNamedChildNames*(node: TSNode): seq[string] =
if node.tsNodeNamedChildCount() != 0: if node.tsNodeNamedChildCount() != 0: