github.com/anthonyme00/gomarkdoc@v1.0.0/lang/func.go (about)

     1  package lang
     2  
     3  import (
     4  	"fmt"
     5  	"go/doc"
     6  	"go/token"
     7  	"strings"
     8  )
     9  
    10  // Func holds documentation information for a single func declaration within a
    11  // package or type.
    12  type Func struct {
    13  	cfg      *Config
    14  	doc      *doc.Func
    15  	examples []*doc.Example
    16  }
    17  
    18  // NewFunc creates a new Func from the corresponding documentation construct
    19  // from the standard library, the related token.FileSet for the package and
    20  // the list of examples for the package.
    21  func NewFunc(cfg *Config, doc *doc.Func, examples []*doc.Example) *Func {
    22  	return &Func{cfg, doc, examples}
    23  }
    24  
    25  // Level provides the default level at which headers for the func should be
    26  // rendered in the final documentation.
    27  func (fn *Func) Level() int {
    28  	return fn.cfg.Level
    29  }
    30  
    31  // Name provides the name of the function.
    32  func (fn *Func) Name() string {
    33  	return fn.doc.Name
    34  }
    35  
    36  // Title provides the formatted name of the func. It is primarily designed for
    37  // generating headers.
    38  func (fn *Func) Title() string {
    39  	if fn.doc.Recv != "" {
    40  		return fmt.Sprintf("func (%s) %s", fn.doc.Recv, fn.doc.Name)
    41  	}
    42  
    43  	return fmt.Sprintf("func %s", fn.doc.Name)
    44  }
    45  
    46  // Receiver provides the type of the receiver for the function, or empty string
    47  // if there is no receiver type.
    48  func (fn *Func) Receiver() string {
    49  	return fn.doc.Recv
    50  }
    51  
    52  // Location returns a representation of the node's location in a file within a
    53  // repository.
    54  func (fn *Func) Location() Location {
    55  	return NewLocation(fn.cfg, fn.doc.Decl)
    56  }
    57  
    58  // Summary provides the one-sentence summary of the function's documentation
    59  // comment
    60  func (fn *Func) Summary() string {
    61  	return extractSummary(fn.doc.Doc)
    62  }
    63  
    64  // Doc provides the structured contents of the documentation comment for the
    65  // function.
    66  func (fn *Func) Doc() *Doc {
    67  	return NewDoc(fn.cfg.Inc(1), fn.doc.Doc)
    68  }
    69  
    70  // Signature provides the raw text representation of the code for the
    71  // function's signature.
    72  func (fn *Func) Signature() (string, error) {
    73  	// We use a custom FileSet so that we don't inherit multiline formatting
    74  	return printNode(fn.doc.Decl, token.NewFileSet())
    75  }
    76  
    77  // Examples provides the list of examples from the list given on initialization
    78  // that pertain to the function.
    79  func (fn *Func) Examples() (examples []*Example) {
    80  	var fullName string
    81  	if fn.doc.Recv != "" {
    82  		fullName = fmt.Sprintf("%s_%s", fn.rawRecv(), fn.doc.Name)
    83  	} else {
    84  		fullName = fn.doc.Name
    85  	}
    86  	underscorePrefix := fmt.Sprintf("%s_", fullName)
    87  
    88  	for _, example := range fn.examples {
    89  		var name string
    90  		switch {
    91  		case example.Name == fullName:
    92  			name = ""
    93  		case strings.HasPrefix(example.Name, underscorePrefix):
    94  			name = example.Name[len(underscorePrefix):]
    95  		default:
    96  			// TODO: better filtering
    97  			continue
    98  		}
    99  
   100  		examples = append(examples, NewExample(fn.cfg.Inc(1), name, example))
   101  	}
   102  
   103  	return
   104  }
   105  
   106  // Anchor produces anchor text for the func.
   107  func (fn *Func) Anchor() string {
   108  	if fn.doc.Recv != "" {
   109  		return Symbol{
   110  			Kind:     MethodSymbolKind,
   111  			Receiver: fn.doc.Recv,
   112  			Name:     fn.doc.Name,
   113  		}.Anchor()
   114  	}
   115  
   116  	return Symbol{
   117  		Kind: FuncSymbolKind,
   118  		Name: fn.doc.Name,
   119  	}.Anchor()
   120  }
   121  
   122  func (fn *Func) rawRecv() string {
   123  	// remove type parameters
   124  	recv := strings.Split(fn.doc.Recv, "[")[0]
   125  
   126  	if strings.HasPrefix(recv, "*") {
   127  		return recv[1:]
   128  	}
   129  
   130  	return recv
   131  }