<commit_before>// Copyright 2014 AKUALAB INC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
optioner is a tool to generate functional options. Intended to be
used with go generate; see the invocation in example/example.go.

To learn about functional options, see:
http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
http://commandcenter.blogspot.com.au/2014/01/self-referential-functions-and-design.html

This code was adapted from the stringer cmd (golang.org/x/tools/cmd/stringer/).

optioner will generate a file with code of the form:

  // N sets field N in Example.
  func N(n int) Option {
	  return func(ex *Example) {
		  ex.N = n
	  }
  }

The file is created in the package where the code is generated.

optioner will create options for all the fields in the struct except those that include
the tag `opt:"-"`.

For example, given this snippet,

  package example

  //go:generate optioner -type Example
  type Example struct {
	  N      int
	  FSlice []float64 `json:"float_slice"`
	  Map    map[string]int
	  Name   string `opt:"-" json:"name"`
	  ff     func(int) int
  }

  func NewExample(name string, options ...Option) *Example {

	  // Set required values and initialize optional fields with default values.
	  ex := &Example{
		  Name:   name,
		  N:      10,
		  FSlice: make([]float64, 0, 100),
		  Map:    make(map[string]int),
		  ff:     func(n int) int { return n },
	  }

	  // Set options.
	  ex.init(options...)
  }

go generate will generate option functions for fields N, FSlice, Map, and ff. Your package
users can now set options as follows:

  myFunc := func(n int) int {return 2 * n}
  ex := example.NewExample("test", example.N(22), example.Ff(myFunc))

the new struct "ex" will use default values for "FSlice" and "Map", and custom values for
"N" and "ff". Because the argument "name" is required, the field "name" is excluded using a tag.

struct fields don't need to exported, however, the corresponding option will be exported by
capitalizing the first letter.
*/
package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/format"
	"go/parser"
	"go/token"
	"io/ioutil"
	"log"
	"os"
	"reflect"
	"strings"

	"golang.org/x/tools/go/types"
)

var typeNameArg = flag.String("type", "", "type name of the options struct; must be set")
var output = flag.String("output", "", "output file name; default srcdir/<type>_gen_opt.go")

// Usage is a replacement usage function for the flags package.
func Usage() {
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "\toptioner [flags] -type T\n")
	fmt.Fprintf(os.Stderr, "Use struct tag ```opt:\"-\"``` to exclude fields\n")
	fmt.Fprintf(os.Stderr, "For more information, see:\n")
	fmt.Fprintf(os.Stderr, "\thttp://github.com/akualab/optioner\n")<commit_msg>Edit comment.<commit_after>// Copyright 2014 AKUALAB INC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
optioner is a tool to generate functional options. Intended to be
used with go generate; see the invocation in example/example.go.

To learn about functional options, see:
http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
http://commandcenter.blogspot.com.au/2014/01/self-referential-functions-and-design.html

This code was adapted from the stringer cmd (golang.org/x/tools/cmd/stringer/).

optioner will generate a file with code of the form:

  // N sets field N in Example.
  func N(n int) Option {
	  return func(ex *Example) {
		  ex.N = n
	  }
  }

The file is created in the package where the code is generated.

optioner will create options for all the fields in the struct except those that include
the tag `opt:"-"`.

For example, given this snippet,

  package example

  //go:generate optioner -type Example
  type Example struct {
	  N      int
	  FSlice []float64 `json:"float_slice"`
	  Map    map[string]int
	  Name   string `opt:"-" json:"name"`
	  ff     func(int) int
  }

  func NewExample(name string, options ...Option) *Example {

	  // Set required values and initialize optional fields with default values.
	  ex := &Example{
		  Name:   name,
		  N:      10,
		  FSlice: make([]float64, 0, 100),
		  Map:    make(map[string]int),
		  ff:     func(n int) int { return n },
	  }

	  // Set options.
	  ex.init(options...)
  }

go generate will generate option functions for fields N, FSlice, Map, and ff. Your package
users can now set options as follows:

  myFunc := func(n int) int {return 2 * n}
  ex := example.NewExample("test", example.N(22), example.Ff(myFunc))

the new struct "ex" will use default values for "FSlice" and "Map", and custom values for
"N" and "ff". Because the argument "name" is required, the field "name" is excluded using a tag.

struct fields don't need to be exported, however, the corresponding option will be exported by
capitalizing the first letter. Documentation for options is also auto-generated.
*/
package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/format"
	"go/parser"
	"go/token"
	"io/ioutil"
	"log"
	"os"
	"reflect"
	"strings"

	"golang.org/x/tools/go/types"
)

var typeNameArg = flag.String("type", "", "type name of the options struct; must be set")
var output = flag.String("output", "", "output file name; default srcdir/<type>_gen_opt.go")

// Usage is a replacement usage function for the flags package.
func Usage() {
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
	fmt.Fprintf(os.Stderr, "\toptioner [flags] -type T\n")
	fmt.Fprintf(os.Stderr, "Use struct tag ```opt:\"-\"``` to exclude fields\n")
	fmt.Fprintf(os.Stderr, "For more information, see:\n")
	fmt.Fprintf(os.Stderr, "\thttp://github.com/akualab/optioner\n")
{'fraction_non_alphanumeric': 0.1236882848787201, 'fraction_numerical': 0.011009805608119731, 'mean_word_length': 3.458588957055215, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7165545', 'n_tokens_mistral': 2013, 'n_tokens_neox': 1874, 'n_words': 691}