From 931e7ac1a614f1fca33cd5bbf026cc061e196dcb Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Mon, 21 Jul 2025 12:59:16 -0500 Subject: [PATCH] used gemini to make function docs --- Makefile | 7 +++ protoReformat.go | 118 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 105 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index 3bc0cb7..5b37cf5 100644 --- a/Makefile +++ b/Makefile @@ -122,3 +122,10 @@ reformat-signal.proto-fruit: goimports vet build reformat-signal.proto-fruit-debug: goimports vet build git checkout example/*.proto make -C example proto-reformat-fruit-debug + +# eh, this is okay for docs I guess. notsure. but it makes pkg.go.dev better +gemini: + DEBUG=1 gemini --prompt "Can you add comments to the functions in the protoReformat.go file? Just add comments at the beginning of each function." --yolo --debug + +gemini-try2: + DEBUG=1 gemini --prompt "First figure out what each GO function in protoReformat.go does. Second, make good comments to put on on each function for pkg.go.dev?" --yolo --debug diff --git a/protoReformat.go b/protoReformat.go index 681cbc2..8b49879 100644 --- a/protoReformat.go +++ b/protoReformat.go @@ -37,6 +37,10 @@ type Message interface { } */ +// protoReformatComments reads a .proto file, processes its comments using +// commentPreprocessor and commentPreprocessorFull, and writes the modified +// content back to the file. This function serves as a dedicated comment +// processing tool. func protoReformatComments(filename string) error { // read in the .proto file data, err := os.ReadFile(filename) @@ -58,6 +62,9 @@ func protoReformatComments(filename string) error { return nil } +// protoReformat reads a .proto file, parses it into a structured format, +// aligns its contents for readability, and writes the formatted output back to +// the original file. It acts as the main entry point for the formatting process. func protoReformat(filename string) error { // read in the .proto file data, err := os.ReadFile(filename) @@ -77,6 +84,18 @@ func protoReformat(filename string) error { return saveFile(filename, newfile) } +// doParse is the core parsing engine for the protoReformat tool. It processes +// the raw lines of a .proto file and constructs a hierarchical tree of +// FormatMsg structs. +// +// This tree mirrors the .proto file's logical structure, representing `message`, +// `enum`, and `oneof` blocks as distinct nodes. The function recursively +// handles nested definitions and carefully preserves associated comments and +// surrounding whitespace, which are essential for the final formatting. +// +// The returned *FormatMsg is the root of this tree, containing the complete, +// structured representation of the file, which is then used by the format +// functions to generate a clean, aligned output. func doParse(lines []string) *FormatMsg { var comments string @@ -156,6 +175,9 @@ func doParse(lines []string) *FormatMsg { return basemsg } +// saveFile writes the provided data to a specified file, creating it if it +// doesn't exist or truncating it if it does. It ensures the data is trimmed of +// surrounding whitespace before writing. func saveFile(filename string, data string) error { pf, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { @@ -170,6 +192,9 @@ func saveFile(filename string, data string) error { return nil } +// newDepth creates a new FormatMsg, representing a nested message structure. +// It inherits formatting parameters from its parent and increments the nesting +// depth, which is used to calculate indentation. func newDepth(fmtmsg *FormatMsg, header string) *FormatMsg { newmsg := new(FormatMsg) lastMessage = newmsg @@ -181,6 +206,9 @@ func newDepth(fmtmsg *FormatMsg, header string) *FormatMsg { return newmsg } +// newMessage creates a new FormatMsg of a specified type (e.g., message, enum) +// and appends it to the parent's list of messages. It associates the new +// message with its preceding comments. func (msgPB *FormatMsg) newMessage(header string, comments string, msgType FormatMsg_Type) *FormatMsg { newmsg := newDepth(msgPB, header) newmsg.Type = msgType @@ -192,6 +220,9 @@ func (msgPB *FormatMsg) newMessage(header string, comments string, msgType Forma return newmsg } +// load recursively parses the content within a message, enum, or oneof block. +// It consumes lines from the global line scanner until it reaches the closing +// brace '}' of the current block, creating nested messages as needed. func (msg *FormatMsg) load() { // fmtmsg := msg.msgPB for allTheLines.Scan() { @@ -234,7 +265,10 @@ func (msg *FormatMsg) load() { return } -// returns vartype, varname, id, end +// tokenMsgVar parses a line containing a field definition within a .proto message. +// It extracts and returns the variable type, name, ID, and any trailing comments +// or options. For example, from "string name = 1; // User's name", it returns +// "string", "name", "1", and "// User's name". func tokenMsgVar(line string) (string, string, string, string) { parts := strings.Split(line, ";") front := parts[0] @@ -253,6 +287,8 @@ func tokenMsgVar(line string) (string, string, string, string) { return vartype, varname, id, end } +// slicesPop removes and returns the last element from a slice of strings, +// along with the modified slice. It is a utility function for tokenizing lines. func slicesPop(parts []string) ([]string, string) { if len(parts) == 0 { return nil, "" @@ -265,7 +301,9 @@ func slicesPop(parts []string) ([]string, string) { return parts[0 : x-1], end } -// 'for x := range' syntax using the smartly done golang 1.24 'iter' +// makeLineIter creates a Go 1.24+ style iterator (iter.Seq) from a byte slice +// of file content. This allows for convenient line-by-line iteration using +// `for ... range`. func makeLineIter(data []byte) iter.Seq[string] { items := strings.Split(string(data), "\n") // log.Println("Made All() Iter.Seq[] with length", len(items)) @@ -278,7 +316,9 @@ func makeLineIter(data []byte) iter.Seq[string] { } } -// find the max length of varname and vartype +// setMaxSizes calculates the maximum length of field types and names within a +// message. These values are used later to determine the padding required for +// consistent alignment of fields. func setMaxSizes(curmsg *FormatMsg) { for _, line := range curmsg.Lines { parts := strings.Split(line, ";") @@ -297,7 +337,8 @@ func setMaxSizes(curmsg *FormatMsg) { } } -// use this for header and footer lines +// padBase generates the indentation string for message headers and footers +// based on their nesting depth. func (msg *FormatMsg) padBase() string { var pad string for i := 1; i < int(msg.Depth); i += 1 { @@ -306,7 +347,8 @@ func (msg *FormatMsg) padBase() string { return pad } -// use this for lines inside the message +// pad generates the indentation string for lines inside a message block, +// such as field definitions, based on the message's nesting depth. func (msg *FormatMsg) pad() string { var pad string for i := 0; i < int(msg.Depth); i += 1 { @@ -315,6 +357,8 @@ func (msg *FormatMsg) pad() string { return pad } +// padding generates an indentation string with a custom offset, allowing for +// flexible alignment calculations. func (msg *FormatMsg) padding(offset int) string { var pad string for i := offset; i < int(msg.Depth); i += 1 { @@ -323,6 +367,8 @@ func (msg *FormatMsg) padding(offset int) string { return pad } +// formatEnum formats an enum block, including its header, values, and footer, +// ensuring proper indentation. func formatEnum(curmsg *FormatMsg) []string { var newmsg []string newmsg = append(newmsg, curmsg.formatLineBase(curmsg.Header, "enum header")) @@ -340,6 +386,8 @@ func formatEnum(curmsg *FormatMsg) []string { return newmsg } +// formatOneof formats a oneof block, aligning its fields and comments +// according to the calculated padding. func formatOneof(curmsg *FormatMsg) []string { // curmsg.formatStandardSizes() @@ -360,7 +408,9 @@ func formatOneof(curmsg *FormatMsg) []string { return newmsg } -// set all children to have the same max sizes +// formatStandardSizes traverses the message tree and standardizes the padding +// for field types and names across all sibling messages. This ensures that +// fields in adjacent messages are vertically aligned, improving readability. func (parent *FormatMsg) formatStandardSizes() { var bigType int64 var bigName int64 @@ -406,6 +456,8 @@ func (parent *FormatMsg) formatStandardSizes() { } } +// format is the main formatting dispatcher. It calls the appropriate formatting +// function (formatEnum, formatOneof, or formatMessage) based on the message type. func (parent *FormatMsg) format() []string { parent.formatStandardSizes() @@ -421,6 +473,8 @@ func (parent *FormatMsg) format() []string { } } +// formatFooter formats the closing brace '}' of a message block, applying the +// correct base indentation. func (msg *FormatMsg) formatFooter(line string, dbg string) string { if line == "" { if argv.Debug { @@ -431,6 +485,8 @@ func (msg *FormatMsg) formatFooter(line string, dbg string) string { return msg.formatLineBase(line, "footer") } +// formatPadAfter adds a blank line after a message block if the original +// file contained one, preserving vertical spacing. func (msg *FormatMsg) formatPadAfter() string { if argv.Debug { return msg.formatLineBase("", "pad after") @@ -438,6 +494,8 @@ func (msg *FormatMsg) formatPadAfter() string { return "" } +// formatHeader formats the opening line of a message block (e.g., "message Foo {"), +// aligning any trailing comments. func (msg *FormatMsg) formatHeader(line string, dbg string) string { if line == "" { if msg.Depth != 0 { @@ -463,6 +521,8 @@ func (msg *FormatMsg) formatHeader(line string, dbg string) string { return fmt.Sprintf(hmm, msg.padBase(), start, " ", end) } +// formatLineBase formats a line using the base indentation level, suitable for +// headers, footers, and comments outside of message bodies. func (msg *FormatMsg) formatLineBase(line string, dbg string) string { line = strings.TrimSpace(line) if argv.Debug { @@ -471,6 +531,8 @@ func (msg *FormatMsg) formatLineBase(line string, dbg string) string { return fmt.Sprintf("%s%s", msg.padBase(), line) } +// formatLine formats a line using the standard block indentation, suitable for +// field definitions and other content inside a message body. func (msg *FormatMsg) formatLine(line string, dbg string) string { line = strings.TrimSpace(line) if argv.Debug { @@ -479,6 +541,8 @@ func (msg *FormatMsg) formatLine(line string, dbg string) string { return fmt.Sprintf("%s%s", msg.pad(), line) } +// formatComment formats a comment line, aligning it with the surrounding code +// based on the calculated maximum field widths. func (msg *FormatMsg) formatComment(line string, dbg string) string { line = strings.TrimSpace(line) pad := fmt.Sprintf("%d", msg.MaxVartype+msg.MaxVarname+13) // 21 is correct? @@ -490,6 +554,8 @@ func (msg *FormatMsg) formatComment(line string, dbg string) string { return fmt.Sprintf("%s%s", msg.pad(), comment) } +// formatVarLine formats a field definition line, padding the type and name to +// ensure vertical alignment with other fields in the same scope. func (msg *FormatMsg) formatVarLine(line string, dbg string) string { line = strings.TrimSpace(line) mt := fmt.Sprintf("%d", msg.MaxVartype) @@ -510,6 +576,9 @@ func (msg *FormatMsg) formatVarLine(line string, dbg string) string { return fmt.Sprintf("%s%s", msg.pad(), newline) } +// formatMsgLine is a dispatcher for formatting a single line within a message. +// It determines whether the line is a comment or a field definition and calls +// the appropriate formatting function. func (msg *FormatMsg) formatMsgLine(line string, dbg string) string { line = strings.TrimSpace(line) if line == "" { @@ -525,11 +594,15 @@ func (msg *FormatMsg) formatMsgLine(line string, dbg string) string { return msg.formatVarLine(line, "var "+dbg) } -// chop extra spaces and blank lines +// trimLines removes leading/trailing whitespace and blank lines from a slice +// of strings by joining and splitting them. func trimLines(lines []string) []string { return strings.Split(strings.TrimSpace(strings.Join(lines, "\n")), "\n") } +// formatMessage is the main function for formatting a `message` block. It +// orchestrates the formatting of comments, nested messages, and field +// definitions to produce a clean, aligned output. func formatMessage(curmsg *FormatMsg) []string { var newmsg []string @@ -620,11 +693,14 @@ func formatMessage(curmsg *FormatMsg) []string { } // DEFINE THE Lines ITERATOR. -// itializes a new iterator. + +// newLinesScanner initializes a new LinesScanner iterator with a slice of strings. func newLinesScanner(things []string) *LinesScanner { return &LinesScanner{things: things} } +// LinesScanner provides an iterator over a slice of strings, allowing for +// sequential access and the ability to un-scan (step back). type LinesScanner struct { sync.Mutex @@ -632,6 +708,8 @@ type LinesScanner struct { index int } +// Scan advances the iterator to the next line. It returns false if there are +// no more lines. func (it *LinesScanner) Scan() bool { if it.index >= len(it.things) { return false @@ -642,6 +720,8 @@ func (it *LinesScanner) Scan() bool { return true } +// UnScan moves the iterator back one line. It returns false if the iterator +// is already at the beginning. func (it *LinesScanner) UnScan() bool { if it.index < 1 { it.index = 0 @@ -653,7 +733,7 @@ func (it *LinesScanner) UnScan() bool { return true } -// does no cleaning of the data +// NextRaw returns the current line from the scanner without any modification. func (it *LinesScanner) NextRaw() string { if it.index-1 == len(it.things) { fmt.Println("Next() error in LinesScanner", it.index) @@ -661,7 +741,8 @@ func (it *LinesScanner) NextRaw() string { return it.things[it.index-1] } -// trims whitespace +// Next returns the current line from the scanner with leading and trailing +// whitespace removed. func (it *LinesScanner) Next() string { if it.index-1 == len(it.things) { fmt.Println("Next() error in LinesScanner", it.index) @@ -674,8 +755,9 @@ func (it *LinesScanner) Next() string { // END DEFINE THE ITERATOR -// turns: "/* test */ reserved /* linkPreviews */ 4;" -// into: reserved 1; // test // linkPreviews +// commentPreprocessor converts single-line C-style block comments (/* ... */) +// into Go-style line comments (// ...) appended to the end of the line. +// For example, "/* test */ reserved 4;" becomes "reserved 4; // test". func commentPreprocessor(line string) string { // Match all /* comment */ blocks re := regexp.MustCompile(`/\*([^*]+)\*/`) @@ -701,14 +783,8 @@ func commentPreprocessor(line string) string { return line } -// /* this -// - thing -// */ -// -// becomes -// -// this -// thing +// commentPreprocessorFull transforms multi-line C-style block comments +// (/* ... */) into a series of single-line Go-style comments (// ...). func commentPreprocessorFull(full string) string { // Match all /* comment */ blocks // re := regexp.MustCompile(`/\*([^*]+)\*/`) @@ -741,6 +817,8 @@ func commentPreprocessorFull(full string) string { }) } +// trimCommentPrefix is a helper function for commentPreprocessorFull that +// removes leading comment markers like '/*', '*', and '*/' from a line. func trimCommentPrefix(line string) string { trimmed := strings.TrimSpace(line)