gadget

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2023 License: MIT Imports: 14 Imported by: 0

README

Gadget

CI Status Release Status GoDoc Go report

gadget is a tool that allows you to quickly inspect your Go source code. It's effectively a small layer of abstraction built on top of the Go AST package.

It inspects your go code, hence the name: Go-go Gadget!

Why?

I was working on another project of mine and thought to myself, "It would be nice if I didn't have to constantly update this readme file every time I made a change." So, I started digging around Go's AST package and came up with gadget.

But, pkg.go.dev already does this ...

Yeah, I know. But, I didn't fully realise I was writing a crappier version of pkg.go.dev until about 90% into the project.

  • Maybe you don't want people to leave your repository to understand the basics of your package's API.
  • Maybe you want to present this data in a different, more personalised, format.
  • Maybe you can use this to write a basic linter, or just learn more about Go AST.

It was fun to write and I use the tool almost daily. Perhaps you'll find it useful as well.

Download & Install

Binary releases are regularly published for the most common operating systems and CPU architectures. These can be downloaded from the releases page. Presentingly, gadget has been tested on, and compiled for, the following:

  1. Windows on 386, arm, amd64
  2. MacOS ( debian ) on amd64, arm64
  3. Linux on 386, arm, amd64, arm64

Download the appropriate archive and unpack the binary into your machine's local $PATH.

Usage

Once added to your machine's local $PATH you can invoke gadget like so:

$ gadget --help
NAME:
   gadget - inspect your code via a small layer of abstraction over Go's AST package

USAGE:
   gadget [global options] command [command options] [arguments...]

VERSION:
   v0.0.12

AUTHOR:
   Wilhelm Murdoch <wilhelm@devilmayco.de>

COMMANDS:
   help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --source value, -s value    path to the target go source file, or directory containing go source files. (default: ".")
   --format value, -f value    the output format of the results as json, template or debug. (default: "json")
   --template value, -t value  if the template format is selected, this is the path to the template file to use. (default: "README.tpl")
   --help, -h                  show help (default: false)
   --version, -v               print only the version (default: false)

COPYRIGHT:
   (c) 2022 Wilhelm Codes ( https://wilhelm.codes )
Example Mapping

One of the primary goals of this project was to link example functions to their associated functions and methods. As I'm regenerating templates, I'd like to have the example body as well as the expected output to live alongside the associated function so I can easily reference it within the Go template.

JSON

Invoking the command with no flags will result in gadget searching for *.go files by recursively walking through the present working directory. Results will be displayed as a JSON object following this structure:

  • packages: a list of discovered packages.
    • files: any *.go file associated with the package.
      • types: discovered types, eg; structs, interfaces, etc...
        • fields: a list of fields associated with each type.
      • functions: functions and methods
        • examples: mapped example functions ( if any )
      • values: explicitly-declared values, eg; constants and variables

A full example of the JSON object can be found in here.

Debug

When invoking gadget using the --format debug flag, you will get output representing all evaluated source code using ast.Print(...). Use this to follow the structure of the AST.

$ gadget --source /path/to/my/project --format debug
... heaps of AST output ...
1298  .  .  15: *ast.FuncDecl {
1299  .  .  .  Doc: *ast.CommentGroup {
1300  .  .  .  .  List: []*ast.Comment (len = 1) {
1301  .  .  .  .  .  0: *ast.Comment {
1302  .  .  .  .  .  .  Slash: sink/sink.go:81:1
1303  .  .  .  .  .  .  Text: "// GetPrivate is an accessor method that returns a dark secret:"
1304  .  .  .  .  .  }
1305  .  .  .  .  }
1306  .  .  .  }
1307  .  .  .  Recv: *ast.FieldList {
1308  .  .  .  .  Opening: sink/sink.go:82:6
1309  .  .  .  .  List: []*ast.Field (len = 1) {
1310  .  .  .  .  .  0: *ast.Field {
1311  .  .  .  .  .  .  Names: []*ast.Ident (len = 1) {
1312  .  .  .  .  .  .  .  0: *ast.Ident {
1313  .  .  .  .  .  .  .  .  NamePos: sink/sink.go:82:7
1314  .  .  .  .  .  .  .  .  Name: "nst"
1315  .  .  .  .  .  .  .  .  Obj: *ast.Object {
1316  .  .  .  .  .  .  .  .  .  Kind: var
1317  .  .  .  .  .  .  .  .  .  Name: "nst"
1318  .  .  .  .  .  .  .  .  .  Decl: *(obj @ 1310)
1319  .  .  .  .  .  .  .  .  }
1320  .  .  .  .  .  .  .  }
1321  .  .  .  .  .  .  }
... heaps more AST output
Template

Use Go's template engine, along with sprig, to generate technical documents or readme files ( like this one! ).

$ gadget --format template --template README.tpl > README.md

Or, without the --template ... flag as it will use README.tpl as the default template if it exists in the starting directory:

$ gadget --format template > README.md

The best way to understand this is by viewing the following "kitchen sink" examples:

  1. sink/README.tpl is a valid Go template.
  2. sink/README.md was generated using the specified Go template.

Build Locally

gadget makes use of Go's new generics support, so the minimum viable version of the language is 1.18.x. Ensure your local development environment meets this single requirement before continuing. There are also several build flags used when compiling the binary. These populate the output of the gadget --version flag.

$ git clone git@github.com:wilhelm-murdoch/go-gadget.git
$ cd gadget
$ make build
$ ./gadget --version
Version: v99.99.99, Stage: local, Commit: 9932cf9fdc90c0d8223ef85a0fc1ddfa99c28f95, Date: 10-04-2022
Testing

All major functionality of gadget has been covered by testing. You can run the tests, benchmarks and lints using the following set of Makefile targets:

  • make test: run the local testing suite.
  • make lint: run staticcheck on the local source files.
  • make bench: run a series of benchmarks and output the results as cpu.out, mem.out and trace.out
  • make pprof-cpu: run a local webserver on port :8800 displaying CPU usage stats.
  • make pprof-mem: run a local webserver on port :8900 displaying memory usage stats.
  • make trace: view local tracing output from the benchmark run.
  • make coverage: view testing code coverage for the local source files.

API

While gadget is meant to be used as a CLI, there's no reason you can't make use of it as a library to integrate into your own tools. If you were wondering, yes, this readme file was generated by gadget itself.

File field.go
Type Field
  • type Field struct #
  • field.go:11:21 #

Exported Fields:

  1. Name: The name of the field. #
  2. IsExported: Determines whether the field is exported. #
  3. IsEmbedded: Determines whether the field is an embedded type. #
  4. Line: The line number this field appears on in the associated source file. #
  5. Signature: The full definition of the field including name, arguments and return values. #
  6. Comment: Any inline comments associated with the field. #
  7. Doc: The comment block directly above this field's definition. #

Function NewField
  • func NewField(f *ast.Field, parent *File) *Field #
  • field.go:25:33 #

NewField returns a field instance and attempts to populate all associatedfields with meaningful values.


Function Parse
  • func (f *Field) Parse() *Field #
  • field.go:37:56 #

Parse is responsible for browsing through f.astField, f.parent to populatethe current fields's fields. ( Chainable )


Function parseSignature
  • func (f *Field) parseSignature() #
  • field.go:62:70 #

parseSignature determines the position of the current field within theassociated source file and extracts the relevant line of code. We only wantthe content before any inline comments. This will also replace consecutivespaces with a single space.


Function String
  • func (f *Field) String() string #
  • field.go:73:75 #

String implements the Stringer struct and returns the current package's name.


File file.go
Type File
  • type File struct #
  • file.go:14:29 #

Exported Fields:

  1. Name: The basename of the file. #
  2. Path: The full path to the file as specified by the caller. #
  3. Package: The name of the golang package associated with this file. #
  4. IsMain: Determines whether this file is part of package main. #
  5. IsTest: Determines whether this file is for golang tests. #
  6. HasTests: Determines whether this file contains golang tests. #
  7. HasBenchmarks: Determines whether this file contains benchmark tests. #
  8. HasExamples: Determines whether this file contains example tests. #
  9. Imports: A list of strings containing all the current file's package imports. #
  10. Values: A collection of declared golang values. #
  11. Functions: A collection of declared golang functions. #
  12. Types: A collection of declared golang types. #

Function NewFile
  • func NewFile(path string) (*File, error) #
  • file.go:34:50 #

NewFile returns a file instance representing a file within a golang package.This function creates a new token set and parser instance representing thenew file's abstract syntax tree ( AST ).

Examples:

package main

import (
  "fmt"
  "strings"

  "github.com/wilhelm-murdoch/go-gadget"
)

func main() {
    if file, err := gadget.NewFile("sink/sink.go"); err == nil {
    	file.Functions.Each(func(i int, function *gadget.Function) bool {
    		fmt.Printf("%s defined between lines %d and %d\n", function.Name, function.LineStart, function.LineEnd)
    		return false
    	})
    }
}
// Output:
// PrintVars defined between lines 30 and 34
// AssignCollection defined between lines 37 and 43
// PrintConst defined between lines 46 and 50
// NewNormalStructTest defined between lines 72 and 79
// GetPrivate defined between lines 82 and 84
// GetOccupation defined between lines 87 and 89
// GetFullName defined between lines 92 and 94
// notExported defined between lines 98 and 100
// NewGenericStructTest defined between lines 111 and 113
// GetPrivate defined between lines 116 and 118
// GetFullName defined between lines 121 and 123
// IsBlank defined between lines 126 and 126
package main

import (
  "fmt"
  "strings"

  "github.com/wilhelm-murdoch/go-gadget"
)

func main() {
    if file, err := gadget.NewFile("sink/sink.go"); err == nil {
    	file.Types.Each(func(i int, t *gadget.Type) bool {
    		if t.Fields.Length() > 0 {
    			fmt.Printf("%s is a %s with %d fields:\n", t.Name, t.Kind, t.Fields.Length())
    			t.Fields.Each(func(i int, f *gadget.Field) bool {
    				fmt.Printf("- %s on line %d\n", f.Name, f.Line)
    				return false
    			})
    		}
    		return false
    	})
    }
}
// Output:
// InterfaceTest is a interface with 1 fields:
// - ImplementMe on line 54
// EmbeddedStructTest is a struct with 1 fields:
// - Occupation on line 59
// NormalStructTest is a struct with 5 fields:
// - First on line 64
// - Last on line 65
// - Age on line 66
// - private on line 67
// - EmbeddedStructTest on line 68
// GenericStructTest is a struct with 4 fields:
// - First on line 104
// - Last on line 105
// - Age on line 106
// - private on line 107
package main

import (
  "fmt"
  "strings"

  "github.com/wilhelm-murdoch/go-gadget"
)

func main() {
    var buffer strings.Builder
    if file, err := gadget.NewFile("sink/sink.go"); err == nil {
    	encoder := json.NewEncoder(&buffer)
    	if err := encoder.Encode(file.Values.Items()); err != nil {
    		fmt.Println(err)
    	}
    }
    
    fmt.Println(buffer.String())
}
// Output:
// [{"kind":"const","name":"ONE","line":9,"body":"ONE   = 1 // represents the number 1"},{"kind":"const","name":"TWO","line":10,"body":"TWO   = 2 // represents the number 2"},{"kind":"const","name":"THREE","line":11,"body":"THREE = 3 // represents the number 3"},{"kind":"var","name":"one","line":16,"body":"one   = \"one\"   // represents the english spelling of 1"},{"kind":"var","name":"two","line":17,"body":"two   = \"two\"   // represents the english spelling of 2"},{"kind":"var","name":"three","line":18,"body":"three = \"three\" // represents the english spelling of 3"},{"kind":"var","name":"collection","line":27,"body":"var collection map[string]map[string]string // this should be picked up as an inline comment."}]

Function Parse
  • func (f *File) Parse() *File #
  • file.go:56:68 #

Parse is responsible for walking through the current file's abstract syntaxtree in order to populate it's fields. This includes imports, definedfunctions and methods, structs and interfaces and other declared values.( Chainable )


Function parsePackage
  • func (f *File) parsePackage() #
  • file.go:71:76 #

parsePackage updates the current file with package-related data.


Function parseImports
  • func (f *File) parseImports() #
  • file.go:81:85 #

parseImports is responsible for creating a list of package imports that havebeen defined within the current file and assinging them to the appropriateImports field.


Function parseFunctions
  • func (f *File) parseFunctions() #
  • file.go:90:106 #

parseFunctions is responsible for creating abstract representations offunctions and methods defined within the current file. All functions areadded to the Functions collection.


Function parseTypes
  • func (f *File) parseTypes() #
  • file.go:111:119 #

parseTypes is responsible for creating abstract representations of declaredgolang types defined within the current file. All findings are added to theTypes collection.


Function parseValues
  • func (f *File) parseValues() #
  • file.go:124:134 #

parseValues is responsible for creating abstract representations of variousgeneral values such as const and var blocks. All values are added to theValues collection.


Function walk
  • func (f *File) walk(fn func(ast.Node) bool) #
  • file.go:138:140 #

walk implements the walk interface which is used to step through syntaxtrees via a caller-supplied callback.


Function String
  • func (f *File) String() string #
  • file.go:143:145 #

String implements the Stringer struct and returns the current package's name.


Function GetAstAttributes
  • func (f *File) GetAstAttributes() (*ast.File, *token.FileSet) #
  • file.go:149:151 #

GetAstAttributes returns the values associated with the astFile and tokenSetprivate fields. This is typically used for debug mode.


File function.go
Type Function
  • type Function struct #
  • function.go:16:35 #

Exported Fields:

  1. Name: The name of the function. #
  2. IsTest: Determines whether this is a test. #
  3. IsBenchmark: Determines whether this is a benchmark. #
  4. IsExample: Determines whether this is an example. #
  5. IsExported: Determines whether this function is exported. #
  6. IsMethod: Determines whether this a method. This will be true if this function has a receiver. #
  7. Receiver: If this method has a receiver, this field will refer to the name of the associated struct. #
  8. Doc: The comment block directly above this funciton's definition. #
  9. Output: If IsExample is true, this field should contain the comment block defining expected output. #
  10. Body: The body of this function; everything contained within the opening and closing braces. #
  11. Signature: The full definition of the function including receiver, name, arguments and return values. #
  12. LineStart: The line number in the associated source file where this function is initially defined. #
  13. LineEnd: The line number in the associated source file where the definition block ends. #
  14. LineCount: The total number of lines, including body, the interface occupies. #
  15. Examples: A list of example functions associated with the current function. #

Function NewFunction
  • func NewFunction(fn *ast.FuncDecl, parent *File) *Function #
  • function.go:39:47 #

NewFunction returns a function instance and attempts to populate allassociated fields with meaningful values.


Function Parse
  • func (f *Function) Parse() *Function #
  • function.go:51:72 #

Parse is responsible for browsing through f.astFunc, f.tokenSet and f.astFileto populate the current function's fields. ( Chainable )


Function parseReceiver
  • func (f *Function) parseReceiver() #
  • function.go:76:95 #

parseReceiver attemps to assign the receiver of a method, if one even exists,and assigns it to the Function.Receiver field.


Function parseOutput
  • func (f *Function) parseOutput() #
  • function.go:101:121 #

parseOutput attempts to fetch the expected output block for an examplefunction and pins it to the current Function for future reference. It assumesall comments immediately following the position of string "// Output:"belong to the output block.


Function parseLines
  • func (f *Function) parseLines() #
  • function.go:125:129 #

parseLines determines the current function body's line positions within thecurrently evaluated file.


Function parseBody
  • func (f *Function) parseBody() #
  • function.go:136:145 #

parseBody attempts to make a few adjustments to the *ast.BlockStmt whichrepresents the current function's body. We remove the opening and closingbraces as well as the first occurrent \t sequence on each line. Some peoplewill ask, "wHy dOn't yOu uSe tHe aSt pAcKaGe fOr tHiS" to which I answer,"Because, I'm lazy. We have the file, we know which lines contain the body."


Function parseSignature
  • func (f *Function) parseSignature() #
  • function.go:149:152 #

parseSignature attempts to determine the current function's type and assignsit to the Signature field of struct Function.


Function String
  • func (f *Function) String() string #
  • function.go:155:157 #

String implements the Stringer struct and returns the current package's name.


File package.go
Type Package
  • type Package struct #
  • package.go:9:12 #

Exported Fields:

  1. Name: The name of the current package. #
  2. Files: A collection of golang files associated with this package. #---
Function NewPackage
  • func NewPackage(name string) *Package #
  • package.go:16:21 #

NewPackage returns a Package instance with an initialised collection used forassigning and iterating through files.


Function String
  • func (p *Package) String() string #
  • package.go:24:26 #

String implements the Stringer struct and returns the current package's name.


File type.go
Type Type
  • type Type struct #
  • type.go:20:33 #

Exported Fields:

  1. Name: The name of the struct. #
  2. Kind: Determines the kind of type, eg; interface or struct. #
  3. LineStart: The line number in the associated source file where this struct is initially defined. #
  4. LineEnd: The line number in the associated source file where the definition block ends. #
  5. LineCount: The total number of lines, including body, the struct occupies. #
  6. Comment: Any inline comments associated with the struct. #
  7. Doc: The comment block directly above this struct's definition. #
  8. Signature: The full definition of the struct itself. #
  9. Body: The full body of the struct sourced directly from the associated file; comments included. #
  10. Fields: A collection of fields and their associated metadata. #

Function NewType
  • func NewType(ts *ast.TypeSpec, parent *File) *Type #
  • type.go:37:45 #

NewType returns an struct instance and attempts to populate all associatedfields with meaningful values.


Function Parse
  • func (t *Type) Parse() *Type #
  • type.go:49:56 #

Parse is responsible for browsing through f.astSpec, f.astType, f.parent topopulate the current struct's fields. ( Chainable )


Function parseLines
  • func (t *Type) parseLines() #
  • type.go:60:64 #

parseLines determines the current struct's opening and closing linepositions.


Function parseBody
  • func (t *Type) parseBody() #
  • type.go:69:71 #

parseBody attempts to make a few adjustments to the *ast.BlockStmt whichrepresents the current struct's body. We remove the opening and closingbraces as well as the first occurrent \t sequence on each line.


Function parseSignature
  • func (t *Type) parseSignature() #
  • type.go:75:78 #

parseSignature attempts to determine the current structs's type and assignsit to the Signature field of struct Function.


Function parseFields
  • func (t *Type) parseFields() #
  • type.go:82:103 #

parseFields iterates through the struct's list of defined methods topopulate the Fields collection.


Function String
  • func (t *Type) String() string #
  • type.go:106:108 #

String implements the Stringer struct and returns the current package's name.


File util.go
Type Walker
  • type Walker func(ast.Node) boo #
  • util.go:80:80 #

Function GetLinesFromFile
  • func GetLinesFromFile(path string, from, to int) []byte #
  • util.go:18:46 #

GetLinesFromFile creates a byte reader for the file at the target path andreturns a slice of bytes representing the file content. This slice isrestricted the lines specified by the from and to arguments inclusively.This will return an empty byte if an empty file, or any error, is encountered.


Function WalkGoFiles
  • func WalkGoFiles(path string) (files []string) #
  • util.go:51:61 #

WalkGoFiles recursively moves through the directory tree specified by pathproviding a slice of files matching the *.go extention. Explicitlyspecifying a file will return that file.


Function AdjustSource
  • func AdjustSource(source string, adjustBraces bool) string #
  • util.go:66:77 #

AdjustSource is a convenience function that strips the opening and closingbraces of a function's ( or other things ) body and removes the first \tcharacter on each remaining line.


Function Visit
  • func (w Walker) Visit(node ast.Node) ast.Visitor #
  • util.go:83:88 #

Visit steps through each node within the specified syntax tree.


File value.go
Type Value
  • type Value struct #
  • value.go:9:16 #

Exported Fields:

  1. Kind: Describes the current value's type, eg; CONST or VAR. #
  2. Name: The name of the value. #
  3. Line: The line number within the associated source file in which this value was originally defined. #
  4. Body: The full content of the associated statement. #

Function NewValue
  • func NewValue(id *ast.Ident, parent *File) *Value #
  • value.go:19:26 #

NewValue returns a Value instance.


Function Parse
  • func (v *Value) Parse() *Value #
  • value.go:30:35 #

Parse is responsible for browsing through f.astIdent and f.tokenSet topopulate the current value's fields. ( Chainable )


Function String
  • func (v *Value) String() string #
  • value.go:38:40 #

String implements the Stringer struct and returns the current package's name.


License

Copyright © 2022 Wilhelm Murdoch.

This project is MIT licensed.

Documentation

Index

Examples

Constants

View Source
const (
	KIND_INTERFACE = "interface" // Used if the type is an interface with methods.
	KIND_STRUCT    = "struct"    // Used if the type is a struct with fields.
	KIND_ARRAY     = "array"     // Used for array types.
	KIND_FUNC      = "function"  // Use function types.
	KIND_CHAN      = "channel"   // Used for channel types.
	KIND_MAP       = "map"       // Used for map types.
)

Variables

This section is empty.

Functions

func AdjustSource

func AdjustSource(source string, adjustBraces bool) string

AdjustSource is a convenience function that strips the opening and closing braces of a function's ( or other things ) body and removes the first `\t` character on each remaining line.

func GetLinesFromFile

func GetLinesFromFile(path string, from, to int) []byte

GetLinesFromFile creates a byte reader for the file at the target path and returns a slice of bytes representing the file content. This slice is restricted the lines specified by the `from` and `to` arguments inclusively. This will return an empty byte if an empty file, or any error, is encountered.

func WalkGoFiles

func WalkGoFiles(path string) (files []string)

WalkGoFiles recursively moves through the directory tree specified by `path` providing a slice of files matching the `*.go` extention. Explicitly specifying a file will return that file.

Types

type Field

type Field struct {
	Name       string `json:"name"`              // The name of the field.
	IsExported bool   `json:"is_exported"`       // Determines whether the field is exported.
	IsEmbedded bool   `json:"is_embedded"`       // Determines whether the field is an embedded type.
	Line       int    `json:"line"`              // The line number this field appears on in the associated source file.
	Signature  string `json:"body"`              // The full definition of the field including name, arguments and return values.
	Comment    string `json:"comment,omitempty"` // Any inline comments associated with the field.
	Doc        string `json:"doc,omitempty"`     // The comment block directly above this field's definition.
	// contains filtered or unexported fields
}

Field represents a field used in either a struct or an interface.

func NewField

func NewField(f *ast.Field, parent *File) *Field

NewField returns a field instance and attempts to populate all associated fields with meaningful values.

func (*Field) Parse

func (f *Field) Parse() *Field

Parse is responsible for browsing through f.astField, f.parent to populate the current fields's fields. ( Chainable )

func (*Field) String

func (f *Field) String() string

String implements the Stringer struct and returns the current package's name.

type File

type File struct {
	Name          string                            `json:"name"`           // The basename of the file.
	Path          string                            `json:"path"`           // The full path to the file as specified by the caller.
	Package       string                            `json:"package"`        // The name of the golang package associated with this file.
	IsMain        bool                              `json:"is_main"`        // Determines whether this file is part of package main.
	IsTest        bool                              `json:"is_test"`        // Determines whether this file is for golang tests.
	HasTests      bool                              `json:"has_tests"`      // Determines whether this file contains golang tests.
	HasBenchmarks bool                              `json:"has_benchmarks"` // Determines whether this file contains benchmark tests.
	HasExamples   bool                              `json:"has_examples"`   // Determines whether this file contains example tests.
	Imports       []string                          `json:"imports"`        // A list of strings containing all the current file's package imports.
	Values        *collection.Collection[*Value]    `json:"values"`         // A collection of declared golang values.
	Functions     *collection.Collection[*Function] `json:"functions"`      // A collection of declared golang functions.
	Types         *collection.Collection[*Type]     `json:"types"`          // A collection of declared golang types.
	// contains filtered or unexported fields
}

File represents a single file containing golang code.

func NewFile

func NewFile(path string) (*File, error)

NewFile returns a file instance representing a file within a golang package. This function creates a new token set and parser instance representing the new file's abstract syntax tree ( AST ).

Example (Functions)
if file, err := gadget.NewFile("sink/sink.go"); err == nil {
	file.Functions.Each(func(i int, function *gadget.Function) bool {
		fmt.Printf("%s defined between lines %d and %d\n", function.Name, function.LineStart, function.LineEnd)
		return false
	})
}
Output:

PrintVars defined between lines 30 and 34
AssignCollection defined between lines 37 and 43
PrintConst defined between lines 46 and 50
NewNormalStructTest defined between lines 72 and 79
GetPrivate defined between lines 82 and 84
GetOccupation defined between lines 87 and 89
GetFullName defined between lines 92 and 94
notExported defined between lines 98 and 100
NewGenericStructTest defined between lines 111 and 113
GetPrivate defined between lines 116 and 118
GetFullName defined between lines 121 and 123
IsBlank defined between lines 126 and 126
Example (Json)
var buffer strings.Builder
if file, err := gadget.NewFile("sink/sink.go"); err == nil {
	encoder := json.NewEncoder(&buffer)
	if err := encoder.Encode(file.Values.Items()); err != nil {
		fmt.Println(err)
	}
}

fmt.Println(buffer.String())
Output:

[{"kind":"const","name":"ONE","line":9,"body":"ONE   = 1 // represents the number 1"},{"kind":"const","name":"TWO","line":10,"body":"TWO   = 2 // represents the number 2"},{"kind":"const","name":"THREE","line":11,"body":"THREE = 3 // represents the number 3"},{"kind":"var","name":"one","line":16,"body":"one   = \"one\"   // represents the english spelling of 1"},{"kind":"var","name":"two","line":17,"body":"two   = \"two\"   // represents the english spelling of 2"},{"kind":"var","name":"three","line":18,"body":"three = \"three\" // represents the english spelling of 3"},{"kind":"var","name":"collection","line":27,"body":"var collection map[string]map[string]string // this should be picked up as an inline comment."}]
Example (Structs)
if file, err := gadget.NewFile("sink/sink.go"); err == nil {
	file.Types.Each(func(i int, t *gadget.Type) bool {
		if t.Fields.Length() > 0 {
			fmt.Printf("%s is a %s with %d fields:\n", t.Name, t.Kind, t.Fields.Length())
			t.Fields.Each(func(i int, f *gadget.Field) bool {
				fmt.Printf("- %s on line %d\n", f.Name, f.Line)
				return false
			})
		}
		return false
	})
}
Output:

InterfaceTest is a interface with 1 fields:
- ImplementMe on line 54
EmbeddedStructTest is a struct with 1 fields:
- Occupation on line 59
NormalStructTest is a struct with 5 fields:
- First on line 64
- Last on line 65
- Age on line 66
- private on line 67
- EmbeddedStructTest on line 68
GenericStructTest is a struct with 4 fields:
- First on line 104
- Last on line 105
- Age on line 106
- private on line 107

func (*File) GetAstAttributes added in v0.0.11

func (f *File) GetAstAttributes() (*ast.File, *token.FileSet)

GetAstAttributes returns the values associated with the astFile and tokenSet private fields. This is typically used for debug mode.

func (*File) Parse

func (f *File) Parse() *File

Parse is responsible for walking through the current file's abstract syntax tree in order to populate it's fields. This includes imports, defined functions and methods, structs and interfaces and other declared values. ( Chainable )

func (*File) String

func (f *File) String() string

String implements the Stringer struct and returns the current package's name.

type Function

type Function struct {
	// Comment string `json:"comment,omitempty"`  // Any inline comments associated with the function.
	Name        string                            `json:"name"`               // The name of the function.
	IsTest      bool                              `json:"is_test"`            // Determines whether this is a test.
	IsBenchmark bool                              `json:"is_benchmark"`       // Determines whether this is a benchmark.
	IsExample   bool                              `json:"is_example"`         // Determines whether this is an example.
	IsExported  bool                              `json:"is_exported"`        // Determines whether this function is exported.
	IsMethod    bool                              `json:"is_method"`          // Determines whether this a method. This will be true if this function has a receiver.
	Receiver    string                            `json:"receiver,omitempty"` // If this method has a receiver, this field will refer to the name of the associated struct.
	Doc         string                            `json:"doc,omitempty"`      // The comment block directly above this funciton's definition.
	Output      string                            `json:"output,omitempty"`   // If IsExample is true, this field should contain the comment block defining expected output.
	Body        string                            `json:"body"`               // The body of this function; everything contained within the opening and closing braces.
	Signature   string                            `json:"signature"`          // The full definition of the function including receiver, name, arguments and return values.
	LineStart   int                               `json:"line_start"`         // The line number in the associated source file where this function is initially defined.
	LineEnd     int                               `json:"line_end"`           // The line number in the associated source file where the definition block ends.
	LineCount   int                               `json:"line_count"`         // The total number of lines, including body, the interface occupies.
	Examples    *collection.Collection[*Function] `json:"examples"`           // A list of example functions associated with the current function.
	// contains filtered or unexported fields
}

Function represents a golang function or method along with meaningful fields.

func NewFunction

func NewFunction(fn *ast.FuncDecl, parent *File) *Function

NewFunction returns a function instance and attempts to populate all associated fields with meaningful values.

func (*Function) Parse

func (f *Function) Parse() *Function

Parse is responsible for browsing through f.astFunc, f.tokenSet and f.astFile to populate the current function's fields. ( Chainable )

func (*Function) String

func (f *Function) String() string

String implements the Stringer struct and returns the current package's name.

type Package

type Package struct {
	Name  string                        `json:"name"`  // The name of the current package.
	Files *collection.Collection[*File] `json:"files"` // A collection of golang files associated with this package.
}

Package represents a golang package as well as all associated files, functions and other declarations.

func NewPackage

func NewPackage(name string) *Package

NewPackage returns a Package instance with an initialised collection used for assigning and iterating through files.

func (*Package) String

func (p *Package) String() string

String implements the Stringer struct and returns the current package's name.

type Type

type Type struct {
	Name      string                         `json:"name"`              // The name of the struct.
	Kind      string                         `json:"kind"`              // Determines the kind of type, eg; interface or struct.
	LineStart int                            `json:"line_start"`        // The line number in the associated source file where this struct is initially defined.
	LineEnd   int                            `json:"line_end"`          // The line number in the associated source file where the definition block ends.
	LineCount int                            `json:"line_count"`        // The total number of lines, including body, the struct occupies.
	Comment   string                         `json:"comment,omitempty"` // Any inline comments associated with the struct.
	Doc       string                         `json:"doc,omitempty"`     // The comment block directly above this struct's definition.
	Signature string                         `json:"signature"`         // The full definition of the struct itself.
	Body      string                         `json:"body,omitempty"`    // The full body of the struct sourced directly from the associated file; comments included.
	Fields    *collection.Collection[*Field] `json:"fields,omitempty"`  // A collection of fields and their associated metadata.
	// contains filtered or unexported fields
}

Type represents a golang type definition.

func NewType

func NewType(ts *ast.TypeSpec, parent *File) *Type

NewType returns an struct instance and attempts to populate all associated fields with meaningful values.

func (*Type) Parse

func (t *Type) Parse() *Type

Parse is responsible for browsing through f.astSpec, f.astType, f.parent to populate the current struct's fields. ( Chainable )

func (*Type) String

func (t *Type) String() string

String implements the Stringer struct and returns the current package's name.

type Value

type Value struct {
	Kind string `json:"kind"` // Describes the current value's type, eg; CONST or VAR.
	Name string `json:"name"` // The name of the value.
	Line int    `json:"line"` // The line number within the associated source file in which this value was originally defined.
	Body string `json:"body"` // The full content of the associated statement.
	// contains filtered or unexported fields
}

Value represents a declared value in go; var, const, etc...

func NewValue

func NewValue(id *ast.Ident, parent *File) *Value

NewValue returns a Value instance.

func (*Value) Parse

func (v *Value) Parse() *Value

Parse is responsible for browsing through f.astIdent and f.tokenSet to populate the current value's fields. ( Chainable )

func (*Value) String

func (v *Value) String() string

String implements the Stringer struct and returns the current package's name.

type Walker

type Walker func(ast.Node) bool

walker implements a walker interface used to traversing syntax trees.

func (Walker) Visit

func (w Walker) Visit(node ast.Node) ast.Visitor

Visit steps through each node within the specified syntax tree.

Directories

Path Synopsis
cmd
Package sink covers most, if not all, patterns to adequately-test gadget's capabilities.
Package sink covers most, if not all, patterns to adequately-test gadget's capabilities.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL