gollect

package module
v1.4.0 Latest Latest
Warning

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

Go to latest
Published: Aug 5, 2023 License: BSD-3-Clause Imports: 18 Imported by: 0

README

gollect

CI

README - 日本語

A tool for competitive programming in Go.

Extract only the codes used from main function, apply gofmt and output into one file.

Install

go install github.com/murosan/gollect/cmd/gollect@latest

It parses AST at runtime, so it depends on the GoLang's version installed.
Please reinstall when you upgrade (or downgrade) GoLang.

Usage

Suppose you have implemented the following Min,Max functions in the lib package:

package lib

import "golang.org/x/exp/constraints"

func Min[T constraints.Ordered](a, b T) T {
	if a < b {
		return a
	}
	return b
}

func Max[T constraints.Ordered](a, b T) T {
	if a > b {
		return a
	}
	return b
}

Then implement main package.
The following code reads two numbers and outputs the larger one.

package main

import (
	"fmt"
	"github.com/your-name/repo-name/lib"
)

func main() {
	var a, b int
	fmt.Scan(&a, &b)

	max := lib.Max(a, b)
	fmt.Println(max)
}

Execute gollect.

$ gollect -in ./main.go

The code you can submit will be outputted as follow:

package main

import (
	"fmt"
	"golang.org/x/exp/constraints"
)

func main() {
	var a, b int
	fmt.Scan(&a, &b)

	max := Max(a, b)
	fmt.Println(max)
}

func Max[T constraints.Ordered](a, b T) T {
	if a > b {
		return a
	}
	return b
}

Import statements of self managed package (github.com/your-name/repo-name/lib) and unused Min functions are not included.

The package golang.org/x/exp/constraints is configured to leave by default. The details of settings are described later.

Configuration

You can write configuration file by YAML syntax.
To specify configuration file, run gollect with -config option.

$ gollect -config config.yml
Default values
inputFile: main.go
outputPaths:
  - stdout
thirdPartyPackagePathPrefixes:
  - golang.org/x/exp
  - github.com/emirpasic/gods
  - github.com/liyue201/gostl
  - gonum.org/v1/gonum
Options

You can override default values by specifying each option.
The dafault values are used if the option is omitted.

inputFile
key type description default
inputFile string The filepath main function is written main.go

example:

inputFile: main.go
outputPaths
key type description default
outputPaths []string outputs.
available values: stdout,clipboard,<filepath>
stdout

example:

outputPaths:
  - stdout
  - clipboard
  - out/main.go
thirdPartyPackagePathPrefixes
key type description default
thirdPartyPackagePathPrefixes []string Package-path prefixes that can be used at judge system.
The import statements and package selectors specified here will not be deleted.
golang.org/x/exp
github.com/emirpasic/gods
github.com/liyue201/gostl
gonum.org/v1/gonum

example:

thirdPartyPackagePathPrefixes:
  - golang.org/x/exp
  - github.com/emirpasic/gods
thirdPartyPackagePathPrefixes: []

Other Specification

Struct Methods

Finally, the declaration which is not used from main function will be ignored.
Also methods are not exception.

// input
package main

import "sort"

type S[T ~int | ~string] []T

func (s S[T]) Len() int           { return len(s) }
func (s S[T]) Less(i, j int) bool { return s[i] < s[j] }
func (s S[T]) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

func main() {
	var s S[int]
	sort.Sort(&s)
}
// output
// !! compile error !!
package main

import "sort"

type S[T ~int | ~string] []T

func main() {
	var s S[int]
	sort.Sort(&s)
}

The Len, Less and Swap functions have been removed as they are not used directly from the main function, but the final code will not work without them.
There are two ways to leave them.

1. Embed Interface in Struct field
// input
package main

import "sort"

type S[T ~int | ~string] struct {
	sort.Interface
	data []T
}

func (s *S[T]) Len() int           { return len(s.data) }
func (s *S[T]) Less(i, j int) bool { return s.data[i] < s.data[j] }
func (s *S[T]) Swap(i, j int)      { s.data[i], s.data[j] = s.data[j], s.data[i] }
func (*S[T]) Unused()              {} // will be removed

func main() {
	var s S[int]
	sort.Sort(&s)
}
// output
package main

import "sort"

type S[T ~int | ~string] struct {
	sort.Interface
	data []T
}

func (s *S[T]) Len() int           { return len(s.data) }
func (s *S[T]) Less(i, j int) bool { return s.data[i] < s.data[j] }
func (s *S[T]) Swap(i, j int)      { s.data[i], s.data[j] = s.data[j], s.data[i] }

func main() {
	var s S[int]
	sort.Sort(&s)
}
2. Keep all methods by comment annotation

Write // gollect: keep methods in the Struct comment, and all methods will be left.

// input
package main

import "sort"

// gollect: keep methods
type S[T ~int | ~string] []T

func (s S[T]) Len() int           { return len(s) }
func (s S[T]) Less(i, j int) bool { return s[i] < s[j] }
func (s S[T]) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (S[T]) Unused()              {} // will be left

func main() {
	var s S[int]
	sort.Sort(&s)
}
// output
package main

import "sort"

type S[T ~int | ~string] []T

func (s S[T]) Len() int           { return len(s) }
func (s S[T]) Less(i, j int) bool { return s[i] < s[j] }
func (s S[T]) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (S[T]) Unused()              {} // will be left

func main() {
	var s S[int]
	sort.Sort(&s)
}
Unsupported Statements
cgo
import "C" // cannot use
dot import
package main
import . "fmt" // cannot use
func main() { Println() }
blank import
package pkg
func init() {}
package main
import _ "github.com/owner/repo/pkg" // cannot use
func main() {}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AnalyzeForeach

func AnalyzeForeach(program *Program, initialPkg, initialObj string)

AnalyzeForeach executes analyzing dependency for each packages.

func ExecCheck

func ExecCheck(fset *token.FileSet, pkg *Package)

ExecCheck executes types.Config.Check

func FindFilePaths

func FindFilePaths(path string) (paths []string)

FindFilePaths finds filepaths from package path. https://pkg.go.dev/golang.org/x/tools/go/packages?tab=doc#example-package

func Main

func Main(config *Config) error

Main executes whole program.

func NextPackagePaths

func NextPackagePaths(p *Package) (paths []string)

NextPackagePaths returns list of imported package paths.

func ParseAll

func ParseAll(
	program *Program,
	initialPackage string,
	initialFilePaths []string,
)

ParseAll parses all ast files and sets to Program's map. This also parses external imported package's ast.

func ParseAst

func ParseAst(fset *token.FileSet, p *Package, paths ...string)

ParseAst parses ast and pushes to files slice.

func Write

func Write(w io.Writer, program *Program) error

Write writes filtered and formatted code to io.Writer.

Types

type Annotation

type Annotation string

Annotation is an annotation for doc text.

func (Annotation) String

func (a Annotation) String() string

type CommonDecl

type CommonDecl struct {
	// contains filtered or unexported fields
}

CommonDecl represents one of Var, Const, Func declaration.

func NewCommonDecl

func NewCommonDecl(pkg *Package, ids ...string) *CommonDecl

NewCommonDecl returns new CommonDecl. The length of ids must be one, and the value must be its name.

func (*CommonDecl) GetUses added in v1.4.0

func (d *CommonDecl) GetUses() DeclSet

func (*CommonDecl) ID

func (d *CommonDecl) ID() string

ID returns id made by makeID(package-path, declName).

func (*CommonDecl) IsInitOrUnderScore added in v1.3.0

func (d *CommonDecl) IsInitOrUnderScore() bool

IsInitOrUnderScore return true if the Desc is init func or var declared with underscore.

func (*CommonDecl) IsUsed

func (d *CommonDecl) IsUsed() bool

IsUsed returns true if it is used from main package.

func (*CommonDecl) Node

func (d *CommonDecl) Node() ast.Node

Node returns ast.Node. Its field is initialized lazily.

func (*CommonDecl) Pkg

func (d *CommonDecl) Pkg() *Package

Pkg returns Package.

func (*CommonDecl) SetNode

func (d *CommonDecl) SetNode(n ast.Node)

SetNode sets node.

func (*CommonDecl) String

func (d *CommonDecl) String() string

func (*CommonDecl) Use

func (d *CommonDecl) Use()

Use change this and its dependencies' used field to true.

func (*CommonDecl) Uses

func (d *CommonDecl) Uses(decl Decl)

Uses sets given decl to dependency map.

type Config

type Config struct {
	// path to main.go or glob of main package files
	InputFile string `yaml:"inputFile"`

	// list of output paths
	// filepath, 'stdout' or 'clipboard' are available
	OutputPaths []string `yaml:"outputPaths"`

	// package path prefixes treat as same as builtin packages.
	ThirdPartyPackagePathPrefixes []string `yaml:"thirdPartyPackagePathPrefixes"`
	// contains filtered or unexported fields
}

Config is a configuration.

func DefaultConfig added in v1.4.0

func DefaultConfig() *Config

func LoadConfig

func LoadConfig(path string) *Config

LoadConfig loads config from yaml file.

func UnmarshalConfig added in v1.4.0

func UnmarshalConfig(b []byte) *Config

func (*Config) Validate

func (c *Config) Validate() error

Validate validates configuration.

type Decl

type Decl interface {
	ID() string
	Node() ast.Node
	SetNode(ast.Node)
	Pkg() *Package
	IsUsed() bool
	Use()
	Uses(Decl)
	GetUses() DeclSet
	fmt.Stringer
}

Decl represents a declaration.

func NewDecl

func NewDecl(t DeclType, pkg *Package, ids ...string) Decl

NewDecl return new Decl

type DeclFinder

type DeclFinder struct {
	// contains filtered or unexported fields
}

DeclFinder find package-level declarations and set it to DeclSet.

func NewDeclFinder

func NewDeclFinder(dset DeclSet, iset *ImportSet, pkg *Package) *DeclFinder

NewDeclFinder returns new DeclFinder

func (*DeclFinder) Decl

func (f *DeclFinder) Decl(decl ast.Decl)

Decl finds package-level declarations from ast.Decl.

func (*DeclFinder) Files

func (f *DeclFinder) Files()

Files finds package-level declarations foreach file.decls concurrently.

func (*DeclFinder) FuncDecl

func (f *DeclFinder) FuncDecl(decl *ast.FuncDecl)

FuncDecl finds package-level declarations from ast.FuncDecl.

func (*DeclFinder) GenDecl

func (f *DeclFinder) GenDecl(decl *ast.GenDecl)

GenDecl finds package-level declarations from ast.GenDecl.

type DeclSet

type DeclSet map[string]Decl

DeclSet is a set of Decl

func NewDeclSet

func NewDeclSet() DeclSet

NewDeclSet returns new DeclSet

func (DeclSet) Add

func (s DeclSet) Add(d Decl)

Add adds Decl to set.

func (DeclSet) Each added in v1.4.0

func (s DeclSet) Each(f func(decl Decl))

func (DeclSet) Get

func (s DeclSet) Get(pkg *Package, key ...string) (Decl, bool)

Get gets Decl from set.

func (DeclSet) GetOrCreate

func (s DeclSet) GetOrCreate(dtype DeclType, pkg *Package, key ...string) Decl

GetOrCreate gets Decl from set if exists, otherwise create new one and add to set then returns it.

func (DeclSet) ListInitOrUnderscore added in v1.3.0

func (s DeclSet) ListInitOrUnderscore() (a []Decl)

ListInitOrUnderscore returns Decl list of init func or vars declared with underscore.

func (DeclSet) String

func (s DeclSet) String() string

type DeclType

type DeclType int

DeclType represents declaration type.

const (

	// DecCommon represents common declaration type.
	// e.g, Var, Const, Func
	DecCommon DeclType
	// DecType represents type declaration type.
	// e.g, Struct, Interface
	DecType
	// DecMethod represents method declaration.
	DecMethod
)

func (DeclType) String

func (t DeclType) String() string

type DependencyResolver

type DependencyResolver struct {
	// contains filtered or unexported fields
}

DependencyResolver provides a method for checking dependency.

func NewDependencyResolver

func NewDependencyResolver(dset DeclSet, iset *ImportSet, pset PackageSet) *DependencyResolver

NewDependencyResolver returns new DependencyResolver

func (*DependencyResolver) Check

func (r *DependencyResolver) Check(decl Decl)

Check checks on which given decl depending on.

func (*DependencyResolver) CheckEach added in v1.4.0

func (r *DependencyResolver) CheckEach(initial Decl)

func (*DependencyResolver) CheckEmbedded

func (r *DependencyResolver) CheckEmbedded(decl Decl)

CheckEmbedded checks set a method inherit from to dependency set when the decl is embedded method.

type Filter

type Filter struct {
	// contains filtered or unexported fields
}

Filter provides a method for filtering slice of ast.Decl.

func NewFilter

func NewFilter(dset DeclSet, pkg *Package) *Filter

NewFilter returns new Filter.

func (*Filter) Decls

func (f *Filter) Decls(decls []ast.Decl) (res []ast.Decl)

Decls returns new slice that consists of used declarations. All unused declaration will be removed. Be careful this method manipulates decls directly.

func (*Filter) PackageSelectorExpr

func (f *Filter) PackageSelectorExpr(node ast.Node)

PackageSelectorExpr removes external package's selectors.

fmt.Println() → fmt.Println() // keep builtin packages
mypkg.SomeFunc() → SomeFunc() // remove package selector

type Import

type Import struct {
	// contains filtered or unexported fields
}

Import represents import.

func NewImport

func NewImport(alias, name, path string) *Import

NewImport returns new Import.

func (*Import) IsBuiltin

func (i *Import) IsBuiltin() bool

IsBuiltin returns if the import's path is Go language's builtin or not.

func (*Import) String

func (i *Import) String() string

func (*Import) ToSpec

func (i *Import) ToSpec() *ast.ImportSpec

ToSpec creates and returns ast.ImportSpec.

func (*Import) Use

func (i *Import) Use()

Use changes used state to true.

type ImportSet

type ImportSet struct {
	// contains filtered or unexported fields
}

ImportSet is a set of Import.

func NewImportSet

func NewImportSet() *ImportSet

NewImportSet returns new ImportSet.

func (*ImportSet) AddAndGet added in v1.0.1

func (s *ImportSet) AddAndGet(i *Import) *Import

AddAndGet gets an Import form set if exists, otherwise creates new one and returns it.

func (*ImportSet) GetOrCreate

func (s *ImportSet) GetOrCreate(alias, name, path string) *Import

GetOrCreate gets an Import form set if exists, otherwise creates new one and returns it.

func (*ImportSet) String

func (s *ImportSet) String() string

func (*ImportSet) ToDecl

func (s *ImportSet) ToDecl() *ast.GenDecl

ToDecl creates ast.GenDecl and returns it.

type MethodDecl

type MethodDecl struct {
	*CommonDecl
	// contains filtered or unexported fields
}

MethodDecl represents method declaration.

func NewMethodDecl

func NewMethodDecl(pkg *Package, ids ...string) *MethodDecl

NewMethodDecl returns new MethodDecl. Length of ids must be two, the head value is its receiver's type name and second value is func name.

func (*MethodDecl) IsEmbedded

func (d *MethodDecl) IsEmbedded() bool

IsEmbedded returns true if it is embedded method.

func (*MethodDecl) Name

func (d *MethodDecl) Name() string

Name returns method name.

func (*MethodDecl) SetEmbedded

func (d *MethodDecl) SetEmbedded(b bool)

SetEmbedded change its embedded field to true.

func (*MethodDecl) SetType

func (d *MethodDecl) SetType(t *TypeDecl)

SetType sets given TypeDecl to field.

func (*MethodDecl) Type

func (d *MethodDecl) Type() *TypeDecl

Type returns TypeDecl this method belongs to. The field is initialized lazily.

type Package

type Package struct {
	// contains filtered or unexported fields
}

Package represents analyzing information.

func NewPackage

func NewPackage(path string) *Package

NewPackage returns new Package.

func (*Package) GetObject

func (pkg *Package) GetObject(key string) (*ast.Object, bool)

GetObject gets and returns object which scope is package-level.

func (*Package) Info added in v1.4.0

func (pkg *Package) Info() *types.Info

func (*Package) InitObjects

func (pkg *Package) InitObjects()

InitObjects compiles all files' objects into one map. This is called after parsing all ast files and before start analyzing dependencies.

func (*Package) Path

func (pkg *Package) Path() string

Path returns package path.

func (*Package) PushAstFile

func (pkg *Package) PushAstFile(f *ast.File)

PushAstFile push ast.File to files.

type PackageSet

type PackageSet map[string]*Package

PackageSet is a map of Package.

func (PackageSet) Add

func (p PackageSet) Add(path string, pkg *Package)

Add sets the Package to set.

func (PackageSet) Get

func (p PackageSet) Get(path string) (*Package, bool)

Get gets a Package from set.

type Program

type Program struct {
	// contains filtered or unexported fields
}

Program is a container of information that is necessary across packages.

func NewProgram

func NewProgram() *Program

NewProgram returns new Program.

func (*Program) DeclSet

func (p *Program) DeclSet() DeclSet

DeclSet returns declaration set.

func (*Program) FileSet

func (p *Program) FileSet() *token.FileSet

FileSet returns fileset.

func (*Program) ImportSet

func (p *Program) ImportSet() *ImportSet

ImportSet returns import set.

func (*Program) PackageSet

func (p *Program) PackageSet() PackageSet

PackageSet returns packages.

type TypeDecl

type TypeDecl struct {
	*CommonDecl
	// contains filtered or unexported fields
}

TypeDecl represents Type declaration.

func NewTypeDecl

func NewTypeDecl(pkg *Package, ids ...string) *TypeDecl

NewTypeDecl returns new TypeDecl. The length of ids must be one, and the value must be the type name.

func (*TypeDecl) EachMethod added in v1.4.0

func (d *TypeDecl) EachMethod(f func(m *MethodDecl))

func (*TypeDecl) GetMethod added in v1.4.0

func (d *TypeDecl) GetMethod(m *MethodDecl) (*MethodDecl, bool)

func (*TypeDecl) GetMethodByName added in v1.4.0

func (d *TypeDecl) GetMethodByName(name string) (*MethodDecl, bool)

func (*TypeDecl) KeepMethod

func (d *TypeDecl) KeepMethod()

KeepMethod set true its keep method option. When the field is true, all methods will not removed even the method is not used from main.

func (*TypeDecl) Methods

func (d *TypeDecl) Methods() []*MethodDecl

Methods returns methods as a slice.

func (*TypeDecl) SetMethod

func (d *TypeDecl) SetMethod(m *MethodDecl)

SetMethod sets given method to methods set.

func (*TypeDecl) ShouldKeepMethods added in v1.4.0

func (d *TypeDecl) ShouldKeepMethods() bool

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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