| // Copyright 2018 Google LLC | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| // Package common defines types and utilities common to expression parsing, | |
| // checking, and interpretation | |
| package common | |
| import ( | |
| "strings" | |
| "unicode" | |
| ) | |
| // DocKind indicates the type of documentation element. | |
| type DocKind int | |
| const ( | |
| // DocEnv represents environment variable documentation. | |
| DocEnv DocKind = iota + 1 | |
| // DocFunction represents function documentation. | |
| DocFunction | |
| // DocOverload represents function overload documentation. | |
| DocOverload | |
| // DocVariable represents variable documentation. | |
| DocVariable | |
| // DocMacro represents macro documentation. | |
| DocMacro | |
| // DocExample represents example documentation. | |
| DocExample | |
| // DocField represents documentation for a struct field. | |
| DocField | |
| ) | |
| // Doc holds the documentation details for a specific program element like | |
| // a variable, function, macro, or example. | |
| type Doc struct { | |
| // Kind specifies the type of documentation element (e.g., Function, Variable). | |
| Kind DocKind | |
| // Name is the identifier of the documented element (e.g., function name, variable name). | |
| Name string | |
| // Type is the data type associated with the element, primarily used for variables. | |
| Type string | |
| // Signature represents the function or overload signature. | |
| Signature string | |
| // Description holds the textual description of the element, potentially spanning multiple lines. | |
| Description string | |
| // Children holds nested documentation elements, such as overloads for a function | |
| // or examples for a function/macro. | |
| Children []*Doc | |
| } | |
| // MultilineDescription combines multiple lines into a newline separated string. | |
| func MultilineDescription(lines ...string) string { | |
| return strings.Join(lines, "\n") | |
| } | |
| // ParseDescription takes a single string containing newline characters and splits | |
| // it into a multiline description. All empty lines will be skipped. | |
| // | |
| // Returns an empty string if the input string is empty. | |
| func ParseDescription(doc string) string { | |
| var lines []string | |
| if len(doc) != 0 { | |
| // Split the input string by newline characters. | |
| for _, line := range strings.Split(doc, "\n") { | |
| l := strings.TrimRightFunc(line, unicode.IsSpace) | |
| if len(l) == 0 { | |
| continue | |
| } | |
| lines = append(lines, l) | |
| } | |
| } | |
| // Return an empty slice if the input is empty. | |
| return MultilineDescription(lines...) | |
| } | |
| // ParseDescriptions splits a documentation string into multiple multi-line description | |
| // sections, using blank lines as delimiters. | |
| func ParseDescriptions(doc string) []string { | |
| var examples []string | |
| if len(doc) != 0 { | |
| lines := strings.Split(doc, "\n") | |
| lineStart := 0 | |
| for i, l := range lines { | |
| // Trim trailing whitespace to identify effectively blank lines. | |
| l = strings.TrimRightFunc(l, unicode.IsSpace) | |
| // If a line is blank, it marks the end of the current section. | |
| if len(l) == 0 { | |
| // Start the next section after the blank line. | |
| ex := lines[lineStart:i] | |
| if len(ex) != 0 { | |
| examples = append(examples, MultilineDescription(ex...)) | |
| } | |
| lineStart = i + 1 | |
| } | |
| } | |
| // Append the last section if it wasn't terminated by a blank line. | |
| if lineStart < len(lines) { | |
| examples = append(examples, MultilineDescription(lines[lineStart:]...)) | |
| } | |
| } | |
| return examples | |
| } | |
| // NewVariableDoc creates a new Doc struct specifically for documenting a variable. | |
| func NewVariableDoc(name, celType, description string) *Doc { | |
| return &Doc{ | |
| Kind: DocVariable, | |
| Name: name, | |
| Type: celType, | |
| Description: ParseDescription(description), | |
| } | |
| } | |
| // NewFunctionDoc creates a new Doc struct for documenting a function. | |
| func NewFunctionDoc(name, description string, overloads ...*Doc) *Doc { | |
| return &Doc{ | |
| Kind: DocFunction, | |
| Name: name, | |
| Description: ParseDescription(description), | |
| Children: overloads, | |
| } | |
| } | |
| // NewOverloadDoc creates a new Doc struct for a function example. | |
| func NewOverloadDoc(id, signature string, examples ...*Doc) *Doc { | |
| return &Doc{ | |
| Kind: DocOverload, | |
| Name: id, | |
| Signature: signature, | |
| Children: examples, | |
| } | |
| } | |
| // NewMacroDoc creates a new Doc struct for documenting a macro. | |
| func NewMacroDoc(name, description string, examples ...*Doc) *Doc { | |
| return &Doc{ | |
| Kind: DocMacro, | |
| Name: name, | |
| Description: ParseDescription(description), | |
| Children: examples, | |
| } | |
| } | |
| // NewExampleDoc creates a new Doc struct specifically for holding an example. | |
| func NewExampleDoc(ex string) *Doc { | |
| return &Doc{ | |
| Kind: DocExample, | |
| Description: ex, | |
| } | |
| } | |
| // NewFieldDoc creates a new Doc struct for documenting a struct field. | |
| func NewFieldDoc(name, celType, description string, examples ...*Doc) *Doc { | |
| return &Doc{ | |
| Kind: DocField, | |
| Name: name, | |
| Type: celType, | |
| Description: description, | |
| Children: examples, | |
| } | |
| } | |
| // Documentor is an interface for types that can provide their own documentation. | |
| type Documentor interface { | |
| // Documentation returns the documentation coded by the DocKind to assist | |
| // with text formatting. | |
| Documentation() *Doc | |
| } |