github.com/joomcode/pegomock@v2.9.2-0.20220414140958-14f53b6b2a6c+incompatible/pegomock/main.go (about) 1 // Copyright 2016 Peter Goetz 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "io" 19 "os" 20 "path/filepath" 21 "strings" 22 "time" 23 24 kingpin "gopkg.in/alecthomas/kingpin.v2" 25 26 "github.com/joomcode/pegomock/pegomock/filehandling" 27 "github.com/petergtz/pegomock/pegomock/remove" 28 "github.com/petergtz/pegomock/pegomock/util" 29 "github.com/petergtz/pegomock/pegomock/watch" 30 ) 31 32 var ( 33 app = kingpin.New("pegomock", "Generates mocks based on interfaces.") 34 ) 35 36 func main() { 37 Run(os.Args, os.Stderr, os.Stdin, app, make(chan bool)) 38 } 39 40 func Run(cliArgs []string, out io.Writer, in io.Reader, app *kingpin.Application, done chan bool) { 41 42 workingDir, err := os.Getwd() 43 app.FatalIfError(err, "") 44 45 var ( 46 generateCmd = app.Command("generate", "Generate mocks based on the args provided. ") 47 destination = generateCmd.Flag("output", "Output file; defaults to mock_<interface>_test.go.").Short('o').String() 48 destinationDir = generateCmd.Flag("output-dir", "Output directory; defaults to current directory. If set, package name defaults to this directory, unless explicitly overridden.").String() 49 mockNameOut = generateCmd.Flag("mock-name", "Struct name of the generated mock; defaults to the interface prefixed with Mock").String() 50 packageOut = generateCmd.Flag("package", "Package of the generated code; defaults to the package from which pegomock was executed suffixed with _test").String() 51 // TODO: self_package was taken as is from GoMock. 52 // Still don't understand what it's really there for. 53 // So for now it's not tested. 54 selfPackage = generateCmd.Flag("self_package", "If set, the package this mock will be part of.").String() 55 debugParser = generateCmd.Flag("debug", "Print debug information.").Short('d').Bool() 56 shouldGenerateMatchers = generateCmd.Flag("generate-matchers", "Generate matchers for all non built-in types in a \"matchers\" "+ 57 "directory in the same directory where the mock file gets generated.").Short('m').Default("false").Bool() 58 matchersDestination = generateCmd.Flag("matchers-dir", "Generate matchers in the specified directory; defaults to "+ 59 filepath.Join("<mockdir>", "matchers")).Short('p').String() 60 skipMatchers = generateCmd.Flag("skip-matchers", "A list of types whose matchers shouldn't be generated").String() 61 useExperimentalModelGen = generateCmd.Flag("use-experimental-model-gen", "pegomock includes a new experimental source parser based on "+ 62 "golang.org/x/tools/go/loader. It's currently experimental, but should be more powerful "+ 63 "than the current reflect-based modelgen. E.g. reflect cannot detect method parameter names,"+ 64 " and has to generate them based on a pattern. In a code editor with code assistence, this doesn't provide good help. "+ 65 "\n\nThis option only works when specifying package path + interface, not with .go source files. Also, you can only specify *one* interface. This option cannot be used with the watch command.").Bool() 66 generateCmdArgs = generateCmd.Arg("args", "A (optional) Go package path + space-separated interface or a .go file").Required().Strings() 67 68 watchCmd = app.Command("watch", "Watch over changes in interfaces and regenerate mocks if changes are detected.") 69 watchRecursive = watchCmd.Flag("recursive", "Recursively watch sub-directories as well.").Short('r').Bool() 70 watchPackages = watchCmd.Arg("directories...", "One or more directories of Go packages to watch").Strings() 71 72 removeMocks = app.Command("remove", "Remove mocks generated by Pegomock") 73 removeRecursive = removeMocks.Flag("recursive", "Remove recursively in all sub-directories").Default("false").Short('r').Bool() 74 removeNonInteractive = removeMocks.Flag("non-interactive", "Don't ask for confirmation. Useful for scripts.").Default("false").Short('n').Bool() 75 removeDryRun = removeMocks.Flag("dry-run", "Just show what would be done. Don't delete anything.").Default("false").Short('d').Bool() 76 removeSilent = removeMocks.Flag("silent", "Don't write anything to standard out.").Default("false").Short('s').Bool() 77 removePath = removeMocks.Arg("path", "Use as root directory instead of current working directory.").Default("").String() 78 ) 79 80 app.Writer(out) 81 switch kingpin.MustParse(app.Parse(cliArgs[1:])) { 82 83 case generateCmd.FullCommand(): 84 if err := util.ValidateArgs(*generateCmdArgs); err != nil { 85 app.FatalUsage(err.Error()) 86 } 87 sourceArgs, err := util.SourceArgs(*generateCmdArgs) 88 if err != nil { 89 app.FatalUsage(err.Error()) 90 } 91 92 if *destination != "" && *destinationDir != "" { 93 app.FatalUsage("Cannot use --output and --output-dir together") 94 } 95 96 realPackageOut := *packageOut 97 if *packageOut == "" { 98 realPackageOut, err = DeterminePackageNameIn(workingDir) 99 app.FatalIfError(err, "Could not determine package name.") 100 } 101 102 realDestination := *destination 103 realDestinationDir := workingDir 104 if *destinationDir != "" { 105 realDestinationDir, err = filepath.Abs(*destinationDir) 106 app.FatalIfError(err, "") 107 if *packageOut == "" { 108 realPackageOut = filepath.Base(*destinationDir) 109 } 110 if util.SourceMode(sourceArgs) { 111 realDestination = filepath.Join(*destinationDir, "mock_"+strings.TrimSuffix(sourceArgs[0], ".go")+".go") 112 } else { 113 realDestination = filepath.Join(*destinationDir, "mock_"+strings.ToLower(sourceArgs[len(sourceArgs)-1])+".go") 114 } 115 } 116 117 filehandling.GenerateMockFileInOutputDir( 118 sourceArgs, 119 realDestinationDir, 120 realDestination, 121 *mockNameOut, 122 realPackageOut, 123 *selfPackage, 124 *debugParser, 125 out, 126 *useExperimentalModelGen, 127 *shouldGenerateMatchers, 128 *matchersDestination, 129 *skipMatchers) 130 131 case watchCmd.FullCommand(): 132 var targetPaths []string 133 if len(*watchPackages) == 0 { 134 targetPaths = []string{workingDir} 135 } else { 136 targetPaths = *watchPackages 137 } 138 watch.CreateWellKnownInterfaceListFilesIfNecessary(targetPaths) 139 util.Ticker(watch.NewMockFileUpdater(targetPaths, *watchRecursive).Update, 2*time.Second, done) 140 141 case removeMocks.FullCommand(): 142 path := *removePath 143 if path == "" { 144 var e error 145 path, e = os.Getwd() 146 app.FatalIfError(e, "Could not get current working directory") 147 } 148 remove.Remove(path, *removeRecursive, !*removeNonInteractive, *removeDryRun, *removeSilent, out, in, os.Remove) 149 } 150 }