From 6c2d8950234e5cc2e78f1ea04a02fa26cc1e7e71 Mon Sep 17 00:00:00 2001 From: Ian Norden Date: Fri, 25 Jan 2019 02:59:23 -0600 Subject: [PATCH] composeAndExecute command that loads and executes over arbitrary transformer set exported from a go plugin generated according to config file; test for plugin generation, loading, and execution; work on plugins README --- Gopkg.lock | 9 + cmd/backfillMakerLogs.go | 62 - cmd/composeAndExecute.go | 121 + cmd/continuousLogSync.go | 134 - cmd/root.go | 15 +- environments/compose.toml | 82 + .../shared/transformer}/transformer.go | 19 +- .../transformer/transformer_suite_test.go | 35 + .../shared/transformer/transformer_test.go | 17 + .../shared/{ => watcher}/event_watcher.go | 25 +- .../{ => watcher}/event_watcher_test.go | 90 +- .../watcher_suite_test.go} | 4 +- pkg/autogen/config.go | 23 + pkg/autogen/generator.go | 138 + pkg/autogen/generator_suite_test.go | 35 + pkg/autogen/generator_test.go | 138 + pkg/autogen/test_helpers/bite/initializer.go | 8 + pkg/autogen/test_helpers/database.go | 65 + pkg/autogen/test_helpers/deal/initializer.go | 8 + pkg/autogen/test_helpers/test/README.md | 3 + pkg/omni/full/transformer/transformer_test.go | 2 +- .../light/transformer/transformer_test.go | 4 +- pkg/transformers/bite/config.go | 6 +- pkg/transformers/cat_file/chop_lump/config.go | 6 +- pkg/transformers/cat_file/flip/config.go | 6 +- pkg/transformers/cat_file/pit_vow/config.go | 6 +- pkg/transformers/deal/config.go | 5 +- pkg/transformers/dent/config.go | 5 +- pkg/transformers/drip_drip/config.go | 6 +- pkg/transformers/drip_file/ilk/config.go | 6 +- pkg/transformers/drip_file/repo/config.go | 6 +- pkg/transformers/drip_file/vow/config.go | 6 +- .../factories/log_note_transformer.go | 8 +- .../factories/log_note_transformer_test.go | 8 +- pkg/transformers/factories/transformer.go | 8 +- .../factories/transformer_test.go | 8 +- pkg/transformers/flap_kick/config.go | 6 +- pkg/transformers/flip_kick/config.go | 6 +- pkg/transformers/flop_kick/config.go | 6 +- pkg/transformers/frob/config.go | 6 +- pkg/transformers/integration_tests/bite.go | 3 +- .../integration_tests/cat_file.go | 7 +- pkg/transformers/integration_tests/deal.go | 7 +- pkg/transformers/integration_tests/dent.go | 9 +- .../integration_tests/drip_drip.go | 12 +- .../integration_tests/drip_file_vow.go | 12 +- .../integration_tests/flap_kick.go | 5 +- .../integration_tests/flip_kick.go | 5 +- .../integration_tests/flop_kick.go | 7 +- pkg/transformers/integration_tests/frob.go | 7 +- .../pit_file_debt_ceiling.go | 5 +- .../integration_tests/pit_file_ilk.go | 5 +- .../integration_tests/price_feeds.go | 11 +- pkg/transformers/integration_tests/tend.go | 7 +- .../integration_tests/vat_flux.go | 5 +- .../integration_tests/vat_fold.go | 5 +- .../integration_tests/vat_grab.go | 5 +- .../integration_tests/vat_heal.go | 5 +- .../integration_tests/vat_init.go | 5 +- .../integration_tests/vat_move.go | 5 +- .../integration_tests/vat_slip.go | 5 +- .../integration_tests/vat_tune.go | 5 +- .../integration_tests/vow_flog.go | 5 +- .../pit_file/debt_ceiling/config.go | 6 +- pkg/transformers/pit_file/ilk/config.go | 6 +- pkg/transformers/price_feeds/config.go | 5 +- pkg/transformers/shared/log_chunker.go | 6 +- pkg/transformers/shared/log_chunker_test.go | 19 +- pkg/transformers/tend/config.go | 5 +- pkg/transformers/test_data/generic.go | 9 +- .../test_data/mocks/transformer.go | 13 +- pkg/transformers/transformers.go | 4 +- pkg/transformers/vat_flux/config.go | 6 +- pkg/transformers/vat_fold/config.go | 6 +- pkg/transformers/vat_grab/config.go | 6 +- pkg/transformers/vat_heal/config.go | 6 +- pkg/transformers/vat_init/config.go | 6 +- pkg/transformers/vat_move/config.go | 6 +- pkg/transformers/vat_slip/config.go | 6 +- pkg/transformers/vat_toll/config.go | 6 +- pkg/transformers/vat_tune/config.go | 6 +- pkg/transformers/vow_flog/config.go | 6 +- plugins/README.md | 58 + vendor/github.com/dave/jennifer/.gitignore | 30 + vendor/github.com/dave/jennifer/.travis.yml | 14 + vendor/github.com/dave/jennifer/LICENSE | 21 + vendor/github.com/dave/jennifer/README.md | 1052 ++++++++ vendor/github.com/dave/jennifer/README.md.tpl | 422 +++ .../github.com/dave/jennifer/genjen/data.go | 307 +++ .../github.com/dave/jennifer/genjen/main.go | 17 + .../github.com/dave/jennifer/genjen/render.go | 260 ++ .../dave/jennifer/genjen/render_test.go | 35 + .../dave/jennifer/gennames/README.md | 52 + .../dave/jennifer/gennames/hints.go | 141 + .../github.com/dave/jennifer/gennames/main.go | 29 + vendor/github.com/dave/jennifer/jen/add.go | 19 + .../github.com/dave/jennifer/jen/comments.go | 108 + vendor/github.com/dave/jennifer/jen/custom.go | 61 + vendor/github.com/dave/jennifer/jen/dict.go | 81 + vendor/github.com/dave/jennifer/jen/do.go | 22 + .../dave/jennifer/jen/examples_test.go | 1610 ++++++++++++ vendor/github.com/dave/jennifer/jen/file.go | 262 ++ .../github.com/dave/jennifer/jen/file_test.go | 48 + .../github.com/dave/jennifer/jen/generated.go | 2274 +++++++++++++++++ .../dave/jennifer/jen/generated_test.go | 808 ++++++ vendor/github.com/dave/jennifer/jen/group.go | 147 ++ .../dave/jennifer/jen/group_test.go | 35 + vendor/github.com/dave/jennifer/jen/hints.go | 273 ++ vendor/github.com/dave/jennifer/jen/jen.go | 168 ++ .../github.com/dave/jennifer/jen/jen_test.go | 550 ++++ vendor/github.com/dave/jennifer/jen/lit.go | 154 ++ .../github.com/dave/jennifer/jen/statement.go | 101 + .../dave/jennifer/jen/statement_test.go | 32 + vendor/github.com/dave/jennifer/jen/tag.go | 76 + vendor/github.com/dave/jennifer/jen/tokens.go | 301 +++ vendor/github.com/dave/jennifer/jennifer.go | 9 + 116 files changed, 10554 insertions(+), 454 deletions(-) delete mode 100644 cmd/backfillMakerLogs.go create mode 100644 cmd/composeAndExecute.go delete mode 100644 cmd/continuousLogSync.go create mode 100644 environments/compose.toml rename {pkg/transformers/shared => libraries/shared/transformer}/transformer.go (61%) create mode 100644 libraries/shared/transformer/transformer_suite_test.go create mode 100644 libraries/shared/transformer/transformer_test.go rename libraries/shared/{ => watcher}/event_watcher.go (85%) rename libraries/shared/{ => watcher}/event_watcher_test.go (66%) rename libraries/shared/{shared_suite_test.go => watcher/watcher_suite_test.go} (94%) create mode 100644 pkg/autogen/config.go create mode 100644 pkg/autogen/generator.go create mode 100644 pkg/autogen/generator_suite_test.go create mode 100644 pkg/autogen/generator_test.go create mode 100644 pkg/autogen/test_helpers/bite/initializer.go create mode 100644 pkg/autogen/test_helpers/database.go create mode 100644 pkg/autogen/test_helpers/deal/initializer.go create mode 100644 pkg/autogen/test_helpers/test/README.md create mode 100644 plugins/README.md create mode 100644 vendor/github.com/dave/jennifer/.gitignore create mode 100644 vendor/github.com/dave/jennifer/.travis.yml create mode 100644 vendor/github.com/dave/jennifer/LICENSE create mode 100644 vendor/github.com/dave/jennifer/README.md create mode 100644 vendor/github.com/dave/jennifer/README.md.tpl create mode 100644 vendor/github.com/dave/jennifer/genjen/data.go create mode 100644 vendor/github.com/dave/jennifer/genjen/main.go create mode 100644 vendor/github.com/dave/jennifer/genjen/render.go create mode 100644 vendor/github.com/dave/jennifer/genjen/render_test.go create mode 100644 vendor/github.com/dave/jennifer/gennames/README.md create mode 100644 vendor/github.com/dave/jennifer/gennames/hints.go create mode 100644 vendor/github.com/dave/jennifer/gennames/main.go create mode 100644 vendor/github.com/dave/jennifer/jen/add.go create mode 100644 vendor/github.com/dave/jennifer/jen/comments.go create mode 100644 vendor/github.com/dave/jennifer/jen/custom.go create mode 100644 vendor/github.com/dave/jennifer/jen/dict.go create mode 100644 vendor/github.com/dave/jennifer/jen/do.go create mode 100644 vendor/github.com/dave/jennifer/jen/examples_test.go create mode 100644 vendor/github.com/dave/jennifer/jen/file.go create mode 100644 vendor/github.com/dave/jennifer/jen/file_test.go create mode 100644 vendor/github.com/dave/jennifer/jen/generated.go create mode 100644 vendor/github.com/dave/jennifer/jen/generated_test.go create mode 100644 vendor/github.com/dave/jennifer/jen/group.go create mode 100644 vendor/github.com/dave/jennifer/jen/group_test.go create mode 100644 vendor/github.com/dave/jennifer/jen/hints.go create mode 100644 vendor/github.com/dave/jennifer/jen/jen.go create mode 100644 vendor/github.com/dave/jennifer/jen/jen_test.go create mode 100644 vendor/github.com/dave/jennifer/jen/lit.go create mode 100644 vendor/github.com/dave/jennifer/jen/statement.go create mode 100644 vendor/github.com/dave/jennifer/jen/statement_test.go create mode 100644 vendor/github.com/dave/jennifer/jen/tag.go create mode 100644 vendor/github.com/dave/jennifer/jen/tokens.go create mode 100644 vendor/github.com/dave/jennifer/jennifer.go diff --git a/Gopkg.lock b/Gopkg.lock index bad46b33..6c2cba5f 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -28,6 +28,14 @@ pruneopts = "" revision = "cff30e1d23fc9e800b2b5b4b41ef1817dda07e9f" +[[projects]] + digest = "1:5d47691333460db6ac83ced03c79b4bdb9aff3e322be24affb7855bed8affc6c" + name = "github.com/dave/jennifer" + packages = ["jen"] + pruneopts = "" + revision = "14e399b6b5e8456c66c45c955fc27b568bacb5c9" + version = "v1.3.0" + [[projects]] digest = "1:aaeffbff5bd24654cb4c190ed75d6c7b57b4f5d6741914c1a7a6bb7447e756c5" name = "github.com/deckarep/golang-set" @@ -549,6 +557,7 @@ analyzer-name = "dep" analyzer-version = 1 input-imports = [ + "github.com/dave/jennifer/jen", "github.com/ethereum/go-ethereum", "github.com/ethereum/go-ethereum/accounts/abi", "github.com/ethereum/go-ethereum/accounts/abi/bind", diff --git a/cmd/backfillMakerLogs.go b/cmd/backfillMakerLogs.go deleted file mode 100644 index f6681c78..00000000 --- a/cmd/backfillMakerLogs.go +++ /dev/null @@ -1,62 +0,0 @@ -// VulcanizeDB -// Copyright © 2018 Vulcanize - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package cmd - -import ( - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "github.com/vulcanize/vulcanizedb/libraries/shared" - "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" - "github.com/vulcanize/vulcanizedb/pkg/transformers" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" -) - -// backfillMakerLogsCmd represents the backfillMakerLogs command -var backfillMakerLogsCmd = &cobra.Command{ - Use: "backfillMakerLogs", - Short: "Backfill Maker event logs", - Long: `Backfills Maker event logs based on previously populated block Header records. -This currently includes logs related to Multi-collateral Dai (frob), Auctions (flip-kick), -and Price Feeds (ETH/USD, MKR/USD, and REP/USD - LogValue). - -vulcanizedb backfillMakerLogs --config environments/local.toml - -This command expects a light sync to have been run, and the presence of header records in the Vulcanize database.`, - Run: func(cmd *cobra.Command, args []string) { - backfillMakerLogs() - }, -} - -func backfillMakerLogs() { - blockChain := getBlockChain() - db, err := postgres.NewDB(databaseConfig, blockChain.Node()) - if err != nil { - log.Fatal("Failed to initialize database.") - } - - watcher := shared.NewEventWatcher(db, blockChain) - - watcher.AddTransformers(transformers.TransformerInitializers()) - err = watcher.Execute(constants.HeaderMissing) - if err != nil { - // TODO Handle watcher error in backfillMakerLogs - } -} - -func init() { - rootCmd.AddCommand(backfillMakerLogsCmd) -} diff --git a/cmd/composeAndExecute.go b/cmd/composeAndExecute.go new file mode 100644 index 00000000..4f647802 --- /dev/null +++ b/cmd/composeAndExecute.go @@ -0,0 +1,121 @@ +// Copyright © 2019 Vulcanize, Inc +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package cmd + +import ( + "fmt" + "log" + "os" + "plugin" + "time" + + "github.com/spf13/cobra" + + "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" + "github.com/vulcanize/vulcanizedb/libraries/shared/watcher" + "github.com/vulcanize/vulcanizedb/pkg/autogen" + "github.com/vulcanize/vulcanizedb/utils" +) + +// executePluginCmd represents the execute command +var composeAndExecuteCmd = &cobra.Command{ + Use: "composeAndExecute", + Short: "Composes, loads, and executes transformer initializer plugin", + Long: `This command needs a config .toml file of form: + +[database] + name = "vulcanize_public" + hostname = "localhost" + user = "vulcanize" + password = "vulcanize" + port = 5432 + +[client] + ipcPath = "http://kovan0.vulcanize.io:8545" + +[exporter] + filePath = "~/go/src/github.com/vulcanize/vulcanizedb/plugins" + fileName = "exporter" + [exporter.transformers] + transformerImport1 = "github.com/path_to/transformerInitializer1" + transformerImport2 = "github.com/path_to/transformerInitializer2" + +Note: If any of the imported transformer need additional +config variables do not forget to include those as well + +This information is used to write and build a .so with an arbitrary transformer +set composed from the transformer imports specified in the config file +This .so is loaded as a plugin and the set of transformer initializers is +loaded into and executed over by a generic watcher`, + Run: func(cmd *cobra.Command, args []string) { + composeAndExecute() + }, +} + +func composeAndExecute() { + generator := autogen.NewGenerator(autogenConfig) + err := generator.GenerateTransformerPlugin() + if err != nil { + log.Fatal(err) + } + + ticker := time.NewTicker(pollingInterval) + defer ticker.Stop() + + blockChain := getBlockChain() + db := utils.LoadPostgres(databaseConfig, blockChain.Node()) + + _, pluginPath, err := autogen.GetPaths(autogenConfig) + if err != nil { + log.Fatal(err) + } + + plug, err := plugin.Open(pluginPath) + if err != nil { + log.Fatal(err) + } + + symExporter, err := plug.Lookup("Exporter") + if err != nil { + log.Fatal(err) + } + + exporter, ok := symExporter.(Exporter) + if !ok { + fmt.Println("plugged-in symbol not of type Exporter") + os.Exit(1) + } + + initializers := exporter.Export() + w := watcher.NewWatcher(&db, blockChain) + w.AddTransformers(initializers) + + for range ticker.C { + err := w.Execute() + if err != nil { + // TODO Handle watcher errors in composeAndExecute + } + } +} + +type Exporter interface { + Export() []transformer.TransformerInitializer +} + +func init() { + rootCmd.AddCommand(composeAndExecuteCmd) + composeAndExecuteCmd.Flags().Int64VarP(&startingBlockNumber, "starting-block-number", "s", 0, "Block number to start transformer execution from") +} diff --git a/cmd/continuousLogSync.go b/cmd/continuousLogSync.go deleted file mode 100644 index aa7f9c0f..00000000 --- a/cmd/continuousLogSync.go +++ /dev/null @@ -1,134 +0,0 @@ -// VulcanizeDB -// Copyright © 2018 Vulcanize - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package cmd - -import ( - "fmt" - "time" - - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - - "github.com/vulcanize/vulcanizedb/libraries/shared" - "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" - "github.com/vulcanize/vulcanizedb/pkg/transformers" - shared2 "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" -) - -// continuousLogSyncCmd represents the continuousLogSync command -var continuousLogSyncCmd = &cobra.Command{ - Use: "continuousLogSync", - Short: "Continuously sync logs at the head of the chain", - Long: fmt.Sprintf(`Continously syncs logs based on the configured transformers. - -vulcanizedb continousLogSync --config environments/local.toml - -Available transformers for (optional) selection with --transformers: -%v - -This command expects a light sync to have been run, and the presence of header records in the Vulcanize database.`, - constants.AllTransformerLabels()), - Run: func(cmd *cobra.Command, args []string) { - syncMakerLogs() - }, -} - -var transformerNames []string -var recheckHeadersArg bool - -func syncMakerLogs() { - ticker := time.NewTicker(pollingInterval) - defer ticker.Stop() - - blockChain := getBlockChain() - db, err := postgres.NewDB(databaseConfig, blockChain.Node()) - if err != nil { - log.Fatal("Failed to initialize database.") - } - - initializers := getTransformerInitializers(transformerNames) - - watcher := shared.NewEventWatcher(db, blockChain) - watcher.AddTransformers(initializers) - - for range ticker.C { - if recheckHeadersArg { - err = watcher.Execute(constants.HeaderRecheck) - } else { - err = watcher.Execute(constants.HeaderMissing) - } - if err != nil { - // TODO Handle watcher errors in ContinuousLogSync - } - } -} - -func getTransformerInitializers(transformerNames []string) []shared2.TransformerInitializer { - var initializers []shared2.TransformerInitializer - - if transformerNames[0] == "all" { - initializers = transformers.TransformerInitializers() - } else { - initializerMap := buildTransformerInitializerMap() - for _, transformerName := range transformerNames { - initializers = append(initializers, initializerMap[transformerName]) - } - } - return initializers -} - -func buildTransformerInitializerMap() map[string]shared2.TransformerInitializer { - initializerMap := make(map[string]shared2.TransformerInitializer) - - initializerMap[constants.BiteLabel] = transformers.GetBiteTransformer().NewTransformer - initializerMap[constants.CatFileChopLumpLabel] = transformers.GetCatFileChopLumpTransformer().NewLogNoteTransformer - initializerMap[constants.CatFileFlipLabel] = transformers.GetCatFileFlipTransformer().NewLogNoteTransformer - initializerMap[constants.CatFilePitVowLabel] = transformers.GetCatFilePitVowTransformer().NewLogNoteTransformer - initializerMap[constants.DealLabel] = transformers.GetDealTransformer().NewLogNoteTransformer - initializerMap[constants.DentLabel] = transformers.GetDentTransformer().NewLogNoteTransformer - initializerMap[constants.DripDripLabel] = transformers.GetDripDripTransformer().NewLogNoteTransformer - initializerMap[constants.DripFileIlkLabel] = transformers.GetDripFileIlkTransformer().NewLogNoteTransformer - initializerMap[constants.DripFileRepoLabel] = transformers.GetDripFileRepoTransformer().NewLogNoteTransformer - initializerMap[constants.DripFileVowLabel] = transformers.GetDripFileVowTransformer().NewLogNoteTransformer - initializerMap[constants.FlapKickLabel] = transformers.GetFlapKickTransformer().NewTransformer - initializerMap[constants.FlipKickLabel] = transformers.GetFlipKickTransformer().NewTransformer - initializerMap[constants.FlopKickLabel] = transformers.GetFlopKickTransformer().NewTransformer - initializerMap[constants.FrobLabel] = transformers.GetFrobTransformer().NewTransformer - initializerMap[constants.PitFileDebtCeilingLabel] = transformers.GetPitFileDebtCeilingTransformer().NewLogNoteTransformer - initializerMap[constants.PitFileIlkLabel] = transformers.GetPitFileIlkTransformer().NewLogNoteTransformer - initializerMap[constants.PriceFeedLabel] = transformers.GetPriceFeedTransformer().NewLogNoteTransformer - initializerMap[constants.TendLabel] = transformers.GetTendTransformer().NewLogNoteTransformer - initializerMap[constants.VatFluxLabel] = transformers.GetVatFluxTransformer().NewLogNoteTransformer - initializerMap[constants.VatFoldLabel] = transformers.GetVatFoldTransformer().NewLogNoteTransformer - initializerMap[constants.VatGrabLabel] = transformers.GetVatGrabTransformer().NewLogNoteTransformer - initializerMap[constants.VatHealLabel] = transformers.GetVatHealTransformer().NewLogNoteTransformer - initializerMap[constants.VatInitLabel] = transformers.GetVatInitTransformer().NewLogNoteTransformer - initializerMap[constants.VatMoveLabel] = transformers.GetVatMoveTransformer().NewLogNoteTransformer - initializerMap[constants.VatSlipLabel] = transformers.GetVatSlipTransformer().NewLogNoteTransformer - initializerMap[constants.VatTollLabel] = transformers.GetVatTollTransformer().NewLogNoteTransformer - initializerMap[constants.VatTuneLabel] = transformers.GetVatTuneTransformer().NewLogNoteTransformer - initializerMap[constants.VowFlogLabel] = transformers.GetFlogTransformer().NewLogNoteTransformer - - return initializerMap -} - -func init() { - rootCmd.AddCommand(continuousLogSyncCmd) - continuousLogSyncCmd.Flags().StringSliceVar(&transformerNames, "transformers", []string{"all"}, "transformer names to be run during this command") - continuousLogSyncCmd.Flags().BoolVar(&recheckHeadersArg, "recheckHeaders", false, "checks headers that are already checked for each transformer.") -} diff --git a/cmd/root.go b/cmd/root.go index 6b72c593..af2ea008 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -28,6 +28,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" + "github.com/vulcanize/vulcanizedb/pkg/autogen" "github.com/vulcanize/vulcanizedb/pkg/config" "github.com/vulcanize/vulcanizedb/pkg/geth" "github.com/vulcanize/vulcanizedb/pkg/geth/client" @@ -38,6 +39,7 @@ import ( var ( cfgFile string databaseConfig config.Database + autogenConfig autogen.Config ipc string levelDbPath string startingBlockNumber int64 @@ -53,7 +55,7 @@ const ( var rootCmd = &cobra.Command{ Use: "vulcanizedb", - PersistentPreRun: database, + PersistentPreRun: configure, } func Execute() { @@ -63,7 +65,7 @@ func Execute() { } } -func database(cmd *cobra.Command, args []string) { +func configure(cmd *cobra.Command, args []string) { ipc = viper.GetString("client.ipcpath") levelDbPath = viper.GetString("client.leveldbpath") storageDiffsPath = viper.GetString("filesystem.storageDiffsPath") @@ -74,6 +76,11 @@ func database(cmd *cobra.Command, args []string) { User: viper.GetString("database.user"), Password: viper.GetString("database.password"), } + autogenConfig = autogen.Config{ + FilePath: viper.GetString("exporter.filePath"), + FileName: viper.GetString("exporter.fileName"), + Imports: viper.GetStringMapString("exporter.transformers"), + } viper.Set("database.config", databaseConfig) } @@ -93,6 +100,8 @@ func init() { rootCmd.PersistentFlags().String("client-levelDbPath", "", "location of levelDb chaindata") rootCmd.PersistentFlags().String("datadog-name", "vulcanize-test", "datadog service name") rootCmd.PersistentFlags().String("filesystem-storageDiffsPath", "", "location of storage diffs csv file") + rootCmd.PersistentFlags().String("exporter-path", "~/go/src/github.com/vulcanize/vulcanizedb/plugins", "file path to transformer exporter plugin") + rootCmd.PersistentFlags().String("exporter-name", "exporter", "name of exporter plugin") viper.BindPFlag("database.name", rootCmd.PersistentFlags().Lookup("database-name")) viper.BindPFlag("database.port", rootCmd.PersistentFlags().Lookup("database-port")) @@ -103,6 +112,8 @@ func init() { viper.BindPFlag("client.levelDbPath", rootCmd.PersistentFlags().Lookup("client-levelDbPath")) viper.BindPFlag("datadog.name", rootCmd.PersistentFlags().Lookup("datadog-name")) viper.BindPFlag("filesystem.storageDiffsPath", rootCmd.PersistentFlags().Lookup("filesystem-storageDiffsPath")) + viper.BindPFlag("exporter.filePath", rootCmd.PersistentFlags().Lookup("exporter-path")) + viper.BindPFlag("exporter.fileName", rootCmd.PersistentFlags().Lookup("exporter-name")) } func initConfig() { diff --git a/environments/compose.toml b/environments/compose.toml new file mode 100644 index 00000000..eb3b43d4 --- /dev/null +++ b/environments/compose.toml @@ -0,0 +1,82 @@ +[database] + name = "vulcanize_public" + hostname = "localhost" + user = "vulcanize" + password = "vulcanize" + port = 5432 + +[client] + ipcPath = "http://kovan0.vulcanize.io:8545" + +[datadog] + name = "maker_vdb_staging" + +[exporter] + filePath = "$GOPATH/src/github.com/vulcanize/vulcanizedb/plugins/" + fileName = "exporter" + [exporter.transformers] + bite = "github.com/vulcanize/mcd_transformers/transformers/bite" + cat_chop_lump = "github.com/vulcanize/maker_transformers/cat/chop_lump" + cat_flip = "github.com/vulcanize/mcd_transformers/transformers/cat/flip" + cat_pit_vow = "github.com/vulcanize/mcd_transformers/transformers/cat/pit_vow" + deal = "github.com/vulcanize/mcd_transformers/transformers/deal" + dent = "github.com/vulcanize/mcd_transformers/transformers/dent" + drip_drip = "github.com/vulcanize/mcd_transformers/transformers/drip_drip" + drip_file_ilk = "github.com/vulcanize/mcd_transformers/transformers/drip_file/ilk" + drip_file_repo = "github.com/vulcanize/mcd_transformers/transformers/drip_file/repo" + drip_file_vow = "github.com/vulcanize/mcd_transformers/transformers/drip_file/vow" + flap_kick = "github.com/vulcanize/mcd_transformers/transformers/flap_kick" + flip_kick = "github.com/vulcanize/mcd_transformers/transformers/flip_kick" + flop_kick = "github.com/vulcanize/mcd_transformers/transformers/flop_kick" + frob = "github.com/vulcanize/mcd_transformers/transformers/frob" + pit_file_debt_ceiling = "github.com/vulcanize/mcd_transformers/transformers/pit_file/debt_ceiling" + pit_file_ilk = "github.com/vulcanize/mcd_transformers/transformers/pit_file/ilk" + price_feeds = "github.com/vulcanize/mcd_transformers/transformers/price_feeds" + tend = "github.com/vulcanize/mcd_transformers/transformers/tend" + vat_flux = "github.com/vulcanize/mcd_transformers/transformers/vat_flux" + vat_fold = "github.com/vulcanize/mcd_transformers/transformers/vat_fold" + vat_grab = "github.com/vulcanize/mcd_transformers/transformers/vat_grab" + vat_heal = "github.com/vulcanize/mcd_transformers/transformers/vat_heal" + vat_init = "github.com/vulcanize/mcd_transformers/transformers/vat_init" + vat_move = "github.com/vulcanize/mcd_transformers/transformers/vat_move" + vat_slip = "github.com/vulcanize/mcd_transformers/transformers/vat_slip" + vat_toll = "github.com/vulcanize/mcd_transformers/transformers/vat_toll" + vat_tune = "github.com/vulcanize/mcd_transformers/transformers/vat_tune" + vow_flog = "github.com/vulcanize/mcd_transformers/transformers/vow_flog" + +[contract] + [contract.address] + cat = "0x2f34f22a00ee4b7a8f8bbc4eaee1658774c624e0" + drip = "0x891c04639a5edcae088e546fa125b5d7fb6a2b9d" + eth_flip = "0x32D496Ad866D110060866B7125981C73642cc509" + mcd_flap = "0x8868BAd8e74FcA4505676D1B5B21EcC23328d132" + mcd_flop = "0x6191C9b0086c2eBF92300cC507009b53996FbFFa" + pep = "0xB1997239Cfc3d15578A3a09730f7f84A90BB4975" + pip = "0x9FfFE440258B79c5d6604001674A4722FfC0f7Bc" + pit = "0xe7cf3198787c9a4daac73371a38f29aaeeced87e" + rep = "0xf88bbdc1e2718f8857f30a180076ec38d53cf296" + vat = "0xcd726790550afcd77e9a7a47e86a3f9010af126b" + vow = "0x3728e9777B2a0a611ee0F89e00E01044ce4736d1" + [contract.abi] + cat = '[{"constant":true,"inputs":[],"name":"vat","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x36569e77"},{"constant":true,"inputs":[],"name":"vow","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x626cb3c5"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"flips","outputs":[{"name":"ilk","type":"bytes32"},{"name":"urn","type":"bytes32"},{"name":"ink","type":"uint256"},{"name":"tab","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x70d9235a"},{"constant":true,"inputs":[],"name":"nflip","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x76181a51"},{"constant":true,"inputs":[],"name":"live","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x957aa58c"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"wards","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xbf353dbb"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"ilks","outputs":[{"name":"flip","type":"address"},{"name":"chop","type":"uint256"},{"name":"lump","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xd9638d36"},{"constant":true,"inputs":[],"name":"pit","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xf03c7c6e"},{"inputs":[{"name":"vat_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor","signature":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"ilk","type":"bytes32"},{"indexed":true,"name":"urn","type":"bytes32"},{"indexed":false,"name":"ink","type":"uint256"},{"indexed":false,"name":"art","type":"uint256"},{"indexed":false,"name":"tab","type":"uint256"},{"indexed":false,"name":"flip","type":"uint256"},{"indexed":false,"name":"iArt","type":"uint256"}],"name":"Bite","type":"event","signature":"0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event","signature":"0x644843f351d3fba4abcd60109eaff9f54bac8fb8ccf0bab941009c21df21cf31"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x65fae35e"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x9c52a7f1"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"what","type":"bytes32"},{"name":"data","type":"uint256"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x1a0b287e"},{"constant":false,"inputs":[{"name":"what","type":"bytes32"},{"name":"data","type":"address"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xd4e8be83"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"what","type":"bytes32"},{"name":"flip","type":"address"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xebecb39d"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"urn","type":"bytes32"}],"name":"bite","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x72f7b593"},{"constant":false,"inputs":[{"name":"n","type":"uint256"},{"name":"wad","type":"uint256"}],"name":"flip","outputs":[{"name":"id","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xe6f95917"}]' + drip = '[{"constant":true,"inputs":[],"name":"vat","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x36569e77"},{"constant":true,"inputs":[],"name":"repo","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x56ff3122"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"wards","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xbf353dbb"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"ilks","outputs":[{"name":"vow","type":"bytes32"},{"name":"tax","type":"uint256"},{"name":"rho","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xd9638d36"},{"inputs":[{"name":"vat_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor","signature":"constructor"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event","signature":"0x644843f351d3fba4abcd60109eaff9f54bac8fb8ccf0bab941009c21df21cf31"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x65fae35e"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x9c52a7f1"},{"constant":true,"inputs":[],"name":"era","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x143e55e0"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"vow","type":"bytes32"},{"name":"tax","type":"uint256"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x1a0b287e"},{"constant":false,"inputs":[{"name":"what","type":"bytes32"},{"name":"data","type":"uint256"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x29ae8114"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"}],"name":"drip","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x44e2a5a8"}]' + mcd_flap = '[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"bids","outputs":[{"name":"bid","type":"uint256"},{"name":"lot","type":"uint256"},{"name":"guy","type":"address"},{"name":"tic","type":"uint48"},{"name":"end","type":"uint48"},{"name":"gal","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ttl","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"gem","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"beg","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tau","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kicks","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"dai","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"dai_","type":"address"},{"name":"gem_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"lot","type":"uint256"},{"indexed":false,"name":"bid","type":"uint256"},{"indexed":false,"name":"gal","type":"address"},{"indexed":false,"name":"end","type":"uint48"}],"name":"Kick","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"},{"constant":false,"inputs":[{"name":"gal","type":"address"},{"name":"lot","type":"uint256"},{"name":"bid","type":"uint256"}],"name":"kick","outputs":[{"name":"id","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"lot","type":"uint256"},{"name":"bid","type":"uint256"}],"name":"tend","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"}],"name":"deal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]' + eth_flip = '[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"bids","outputs":[{"name":"bid","type":"uint256"},{"name":"lot","type":"uint256"},{"name":"guy","type":"address"},{"name":"tic","type":"uint48"},{"name":"end","type":"uint48"},{"name":"urn","type":"bytes32"},{"name":"gal","type":"address"},{"name":"tab","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x4423c5f1"},{"constant":true,"inputs":[],"name":"ttl","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x4e8b1dd5"},{"constant":true,"inputs":[],"name":"gem","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x7bd2bea7"},{"constant":true,"inputs":[],"name":"beg","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x7d780d82"},{"constant":true,"inputs":[],"name":"tau","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xcfc4af55"},{"constant":true,"inputs":[],"name":"kicks","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xcfdd3302"},{"constant":true,"inputs":[],"name":"dai","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xf4b9fa75"},{"inputs":[{"name":"dai_","type":"address"},{"name":"gem_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor","signature":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"lot","type":"uint256"},{"indexed":false,"name":"bid","type":"uint256"},{"indexed":false,"name":"gal","type":"address"},{"indexed":false,"name":"end","type":"uint48"},{"indexed":true,"name":"urn","type":"bytes32"},{"indexed":false,"name":"tab","type":"uint256"}],"name":"Kick","type":"event","signature":"0xbac86238bdba81d21995024470425ecb370078fa62b7271b90cf28cbd1e3e87e"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event","signature":"0x644843f351d3fba4abcd60109eaff9f54bac8fb8ccf0bab941009c21df21cf31"},{"constant":true,"inputs":[],"name":"era","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x143e55e0"},{"constant":false,"inputs":[{"name":"urn","type":"bytes32"},{"name":"gal","type":"address"},{"name":"tab","type":"uint256"},{"name":"lot","type":"uint256"},{"name":"bid","type":"uint256"}],"name":"kick","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xeae19d9e"},{"constant":false,"inputs":[{"name":"id","type":"uint256"}],"name":"tick","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xfc7b6aee"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"lot","type":"uint256"},{"name":"bid","type":"uint256"}],"name":"tend","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x4b43ed12"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"lot","type":"uint256"},{"name":"bid","type":"uint256"}],"name":"dent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x5ff3a382"},{"constant":false,"inputs":[{"name":"id","type":"uint256"}],"name":"deal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xc959c42b"}]' + mcd_flop = '[{"constant":true,"inputs":[],"name":"era","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"bids","outputs":[{"name":"bid","type":"uint256"},{"name":"lot","type":"uint256"},{"name":"guy","type":"address"},{"name":"tic","type":"uint48"},{"name":"end","type":"uint48"},{"name":"vow","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ttl","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"lot","type":"uint256"},{"name":"bid","type":"uint256"}],"name":"dent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"gem","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"beg","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"gal","type":"address"},{"name":"lot","type":"uint256"},{"name":"bid","type":"uint256"}],"name":"kick","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"wards","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"id","type":"uint256"}],"name":"deal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tau","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kicks","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"dai","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"dai_","type":"address"},{"name":"gem_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"lot","type":"uint256"},{"indexed":false,"name":"bid","type":"uint256"},{"indexed":false,"name":"gal","type":"address"},{"indexed":false,"name":"end","type":"uint48"}],"name":"Kick","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"}]' + medianizer = '[{"constant":false,"inputs":[{"name":"owner_","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"","type":"bytes32"}],"name":"poke","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"poke","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"compute","outputs":[{"name":"","type":"bytes32"},{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"wat","type":"address"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wat","type":"address"}],"name":"unset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"indexes","outputs":[{"name":"","type":"bytes12"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"next","outputs":[{"name":"","type":"bytes12"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"read","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"peek","outputs":[{"name":"","type":"bytes32"},{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes12"}],"name":"values","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"min_","type":"uint96"}],"name":"setMin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"authority_","type":"address"}],"name":"setAuthority","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"void","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"pos","type":"bytes12"},{"name":"wat","type":"address"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"authority","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"pos","type":"bytes12"}],"name":"unset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"next_","type":"bytes12"}],"name":"setNext","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"min","outputs":[{"name":"","type":"uint96"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"val","type":"bytes32"}],"name":"LogValue","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"authority","type":"address"}],"name":"LogSetAuthority","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"}],"name":"LogSetOwner","type":"event"}]]' + # TODO: replace with updated ABI when contract is deployed (with no pit file stability fee method + modified Frob event) + pit = '[{"constant":true,"inputs":[],"name":"vat","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x36569e77"},{"constant":true,"inputs":[],"name":"live","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x957aa58c"},{"constant":true,"inputs":[],"name":"drip","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x9f678cca"},{"constant":true,"inputs":[],"name":"Line","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xbabe8a3f"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"wards","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xbf353dbb"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"ilks","outputs":[{"name":"spot","type":"uint256"},{"name":"line","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xd9638d36"},{"inputs":[{"name":"vat_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor","signature":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"ilk","type":"bytes32"},{"indexed":true,"name":"urn","type":"bytes32"},{"indexed":false,"name":"ink","type":"uint256"},{"indexed":false,"name":"art","type":"uint256"},{"indexed":false,"name":"dink","type":"int256"},{"indexed":false,"name":"dart","type":"int256"},{"indexed":false,"name":"iArt","type":"uint256"}],"name":"Frob","type":"event","signature":"0xb2afa28318bcc689926b52835d844de174ef8de97e982a85c0199d584920791b"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event","signature":"0x644843f351d3fba4abcd60109eaff9f54bac8fb8ccf0bab941009c21df21cf31"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x65fae35e"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x9c52a7f1"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"what","type":"bytes32"},{"name":"data","type":"uint256"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x1a0b287e"},{"constant":false,"inputs":[{"name":"what","type":"bytes32"},{"name":"data","type":"uint256"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x29ae8114"},{"constant":false,"inputs":[{"name":"what","type":"bytes32"},{"name":"data","type":"address"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xd4e8be83"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"dink","type":"int256"},{"name":"dart","type":"int256"}],"name":"frob","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x5a984ded"}]' + vat = '[{"constant":true,"inputs":[],"name":"debt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x0dca59c1"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"urns","outputs":[{"name":"ink","type":"uint256"},{"name":"art","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x26e27482"},{"constant":true,"inputs":[],"name":"vice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x2d61a355"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"sin","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xa60f1d3e"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"wards","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xbf353dbb"},{"constant":true,"inputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"name":"gem","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xc0912683"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"ilks","outputs":[{"name":"take","type":"uint256"},{"name":"rate","type":"uint256"},{"name":"Ink","type":"uint256"},{"name":"Art","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xd9638d36"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"dai","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xf53e4e69"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor","signature":"constructor"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":true,"name":"too","type":"bytes32"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"Note","type":"event","signature":"0x8c2dbbc2b33ffaa77c104b777e574a8a4ff79829dfee8b66f4dc63e3f8067152"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x65fae35e"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x9c52a7f1"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"}],"name":"init","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x3b663195"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"guy","type":"bytes32"},{"name":"rad","type":"int256"}],"name":"slip","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x42066cbb"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"src","type":"bytes32"},{"name":"dst","type":"bytes32"},{"name":"rad","type":"int256"}],"name":"flux","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xa6e41821"},{"constant":false,"inputs":[{"name":"src","type":"bytes32"},{"name":"dst","type":"bytes32"},{"name":"rad","type":"int256"}],"name":"move","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x78f19470"},{"constant":false,"inputs":[{"name":"i","type":"bytes32"},{"name":"u","type":"bytes32"},{"name":"v","type":"bytes32"},{"name":"w","type":"bytes32"},{"name":"dink","type":"int256"},{"name":"dart","type":"int256"}],"name":"tune","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x5dd6471a"},{"constant":false,"inputs":[{"name":"i","type":"bytes32"},{"name":"u","type":"bytes32"},{"name":"v","type":"bytes32"},{"name":"w","type":"bytes32"},{"name":"dink","type":"int256"},{"name":"dart","type":"int256"}],"name":"grab","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x3690ae4c"},{"constant":false,"inputs":[{"name":"u","type":"bytes32"},{"name":"v","type":"bytes32"},{"name":"rad","type":"int256"}],"name":"heal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x990a5f63"},{"constant":false,"inputs":[{"name":"i","type":"bytes32"},{"name":"u","type":"bytes32"},{"name":"rate","type":"int256"}],"name":"fold","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xe6a6a64d"},{"constant":false,"inputs":[{"name":"i","type":"bytes32"},{"name":"u","type":"bytes32"},{"name":"take","type":"int256"}],"name":"toll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x09b7a0b5"}]' + vow = '[{"constant":true,"inputs":[],"name":"Awe","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"Joy","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"flap","outputs":[{"name":"id","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"hump","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"kiss","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"what","type":"bytes32"},{"name":"data","type":"uint256"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"Ash","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"era","type":"uint48"}],"name":"flog","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"vat","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"Woe","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"wait","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"bump","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"tab","type":"uint256"}],"name":"fess","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"row","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint48"}],"name":"sin","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"flop","outputs":[{"name":"id","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"wards","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"sump","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"Sin","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"what","type":"bytes32"},{"name":"addr","type":"address"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"cow","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"heal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"}]' + [contract.deployment-block] + cat = 8751794 + drip = 8762197 + eth_flip = 8535561 + mcd_flap = 8535544 + mcd_flop = 8535545 + pep = 8760655 + pip = 8760588 + pit = 8535538 + rep = 8760681 + vat = 8535536 + vow = 8751792 diff --git a/pkg/transformers/shared/transformer.go b/libraries/shared/transformer/transformer.go similarity index 61% rename from pkg/transformers/shared/transformer.go rename to libraries/shared/transformer/transformer.go index 7d3c7164..e9e68a5e 100644 --- a/pkg/transformers/shared/transformer.go +++ b/libraries/shared/transformer/transformer.go @@ -1,20 +1,7 @@ -// VulcanizeDB -// Copyright © 2018 Vulcanize +// Auto-gen this code for different transformer interfaces/configs +// based on config file to allow for more modularity -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. - -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package shared +package transformer import ( "github.com/ethereum/go-ethereum/common" diff --git a/libraries/shared/transformer/transformer_suite_test.go b/libraries/shared/transformer/transformer_suite_test.go new file mode 100644 index 00000000..83486c5e --- /dev/null +++ b/libraries/shared/transformer/transformer_suite_test.go @@ -0,0 +1,35 @@ +// VulcanizeDB +// Copyright © 2018 Vulcanize + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package transformer_test + +import ( + "io/ioutil" + "log" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestShared(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Shared Transformer Suite") +} + +var _ = BeforeSuite(func() { + log.SetOutput(ioutil.Discard) +}) diff --git a/libraries/shared/transformer/transformer_test.go b/libraries/shared/transformer/transformer_test.go new file mode 100644 index 00000000..bc6e0255 --- /dev/null +++ b/libraries/shared/transformer/transformer_test.go @@ -0,0 +1,17 @@ +// VulcanizeDB +// Copyright © 2018 Vulcanize + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package transformer_test diff --git a/libraries/shared/event_watcher.go b/libraries/shared/watcher/event_watcher.go similarity index 85% rename from libraries/shared/event_watcher.go rename to libraries/shared/watcher/event_watcher.go index bdcf0554..ef11caef 100644 --- a/libraries/shared/event_watcher.go +++ b/libraries/shared/watcher/event_watcher.go @@ -14,12 +14,15 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -package shared +package watcher import ( "fmt" + "github.com/ethereum/go-ethereum/common" log "github.com/sirupsen/logrus" + + "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" @@ -27,7 +30,7 @@ import ( ) type EventWatcher struct { - Transformers []shared.Transformer + Transformers []transformer.Transformer DB *postgres.DB Fetcher shared.LogFetcher Chunker shared.Chunker @@ -47,16 +50,16 @@ func NewEventWatcher(db *postgres.DB, bc core.BlockChain) EventWatcher { } // Adds transformers to the watcher and updates the chunker, so that it will consider the new transformers. -func (watcher *EventWatcher) AddTransformers(initializers []shared.TransformerInitializer) { +func (watcher *EventWatcher) AddTransformers(initializers []transformer.TransformerInitializer) { var contractAddresses []common.Address var topic0s []common.Hash - var configs []shared.TransformerConfig + var configs []transformer.TransformerConfig for _, initializer := range initializers { - transformer := initializer(watcher.DB) - watcher.Transformers = append(watcher.Transformers, transformer) + t := initializer(watcher.DB) + watcher.Transformers = append(watcher.Transformers, t) - config := transformer.GetConfig() + config := t.GetConfig() configs = append(configs, config) if watcher.StartingBlock == nil { @@ -65,7 +68,7 @@ func (watcher *EventWatcher) AddTransformers(initializers []shared.TransformerIn watcher.StartingBlock = &config.StartingBlockNumber } - addresses := shared.HexStringsToAddresses(config.ContractAddresses) + addresses := transformer.HexStringsToAddresses(config.ContractAddresses) contractAddresses = append(contractAddresses, addresses...) topic0s = append(topic0s, common.HexToHash(config.Topic)) } @@ -105,10 +108,10 @@ func (watcher *EventWatcher) Execute(recheckHeaders constants.TransformerExecuti // Can't quit early and mark as checked if there are no logs. If we are running continuousLogSync, // not all logs we're interested in might have been fetched. - for _, transformer := range watcher.Transformers { - transformerName := transformer.GetConfig().TransformerName + for _, t := range watcher.Transformers { + transformerName := t.GetConfig().TransformerName logChunk := chunkedLogs[transformerName] - err = transformer.Execute(logChunk, header, constants.HeaderMissing) + err = t.Execute(logChunk, header, constants.HeaderMissing) if err != nil { log.Errorf("%v transformer failed to execute in watcher: %v", transformerName, err) return err diff --git a/libraries/shared/event_watcher_test.go b/libraries/shared/watcher/event_watcher_test.go similarity index 66% rename from libraries/shared/event_watcher_test.go rename to libraries/shared/watcher/event_watcher_test.go index 485b3682..345756ab 100644 --- a/libraries/shared/event_watcher_test.go +++ b/libraries/shared/watcher/event_watcher_test.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -package shared_test +package watcher_test import ( "errors" @@ -25,85 +25,85 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/vulcanize/vulcanizedb/libraries/shared" + "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" + "github.com/vulcanize/vulcanizedb/libraries/shared/watcher" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories" "github.com/vulcanize/vulcanizedb/pkg/fakes" - shared2 "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks" "github.com/vulcanize/vulcanizedb/test_config" ) -var _ = Describe("EventWatcher", func() { +var _ = Describe("Watcher", func() { It("initialises correctly", func() { db := test_config.NewTestDB(core.Node{ID: "testNode"}) bc := fakes.NewMockBlockChain() - watcher := shared.NewEventWatcher(db, bc) + w := watcher.NewEventWatcher(db, bc) - Expect(watcher.DB).To(Equal(db)) - Expect(watcher.Fetcher).NotTo(BeNil()) - Expect(watcher.Chunker).NotTo(BeNil()) + Expect(w.DB).To(Equal(db)) + Expect(w.Fetcher).NotTo(BeNil()) + Expect(w.Chunker).NotTo(BeNil()) }) It("adds transformers", func() { - watcher := shared.NewEventWatcher(nil, nil) + w := watcher.NewEventWatcher(nil, nil) fakeTransformer := &mocks.MockTransformer{} fakeTransformer.SetTransformerConfig(mocks.FakeTransformerConfig) - watcher.AddTransformers([]shared2.TransformerInitializer{fakeTransformer.FakeTransformerInitializer}) + w.AddTransformers([]transformer.TransformerInitializer{fakeTransformer.FakeTransformerInitializer}) - Expect(len(watcher.Transformers)).To(Equal(1)) - Expect(watcher.Transformers).To(ConsistOf(fakeTransformer)) - Expect(watcher.Topics).To(Equal([]common.Hash{common.HexToHash("FakeTopic")})) - Expect(watcher.Addresses).To(Equal([]common.Address{common.HexToAddress("FakeAddress")})) + Expect(len(w.Transformers)).To(Equal(1)) + Expect(w.Transformers).To(ConsistOf(fakeTransformer)) + Expect(w.Topics).To(Equal([]common.Hash{common.HexToHash("FakeTopic")})) + Expect(w.Addresses).To(Equal([]common.Address{common.HexToAddress("FakeAddress")})) }) It("adds transformers from multiple sources", func() { - watcher := shared.NewEventWatcher(nil, nil) + w := watcher.NewEventWatcher(nil, nil) fakeTransformer1 := &mocks.MockTransformer{} fakeTransformer1.SetTransformerConfig(mocks.FakeTransformerConfig) fakeTransformer2 := &mocks.MockTransformer{} fakeTransformer2.SetTransformerConfig(mocks.FakeTransformerConfig) - watcher.AddTransformers([]shared2.TransformerInitializer{fakeTransformer1.FakeTransformerInitializer}) - watcher.AddTransformers([]shared2.TransformerInitializer{fakeTransformer2.FakeTransformerInitializer}) + w.AddTransformers([]transformer.TransformerInitializer{fakeTransformer1.FakeTransformerInitializer}) + w.AddTransformers([]transformer.TransformerInitializer{fakeTransformer2.FakeTransformerInitializer}) - Expect(len(watcher.Transformers)).To(Equal(2)) - Expect(watcher.Topics).To(Equal([]common.Hash{common.HexToHash("FakeTopic"), + Expect(len(w.Transformers)).To(Equal(2)) + Expect(w.Topics).To(Equal([]common.Hash{common.HexToHash("FakeTopic"), common.HexToHash("FakeTopic")})) - Expect(watcher.Addresses).To(Equal([]common.Address{common.HexToAddress("FakeAddress"), + Expect(w.Addresses).To(Equal([]common.Address{common.HexToAddress("FakeAddress"), common.HexToAddress("FakeAddress")})) }) It("calculates earliest starting block number", func() { fakeTransformer1 := &mocks.MockTransformer{} - fakeTransformer1.SetTransformerConfig(shared2.TransformerConfig{StartingBlockNumber: 5}) + fakeTransformer1.SetTransformerConfig(transformer.TransformerConfig{StartingBlockNumber: 5}) fakeTransformer2 := &mocks.MockTransformer{} - fakeTransformer2.SetTransformerConfig(shared2.TransformerConfig{StartingBlockNumber: 3}) + fakeTransformer2.SetTransformerConfig(transformer.TransformerConfig{StartingBlockNumber: 3}) - watcher := shared.NewEventWatcher(nil, nil) - watcher.AddTransformers([]shared2.TransformerInitializer{ + w := watcher.NewEventWatcher(nil, nil) + w.AddTransformers([]transformer.TransformerInitializer{ fakeTransformer1.FakeTransformerInitializer, fakeTransformer2.FakeTransformerInitializer, }) - Expect(*watcher.StartingBlock).To(Equal(int64(3))) + Expect(*w.StartingBlock).To(Equal(int64(3))) }) It("returns an error when run without transformers", func() { - watcher := shared.NewEventWatcher(nil, nil) - err := watcher.Execute(constants.HeaderMissing) + w := watcher.NewEventWatcher(nil, nil) + err := w.Execute(constants.HeaderMissing) Expect(err).To(MatchError("No transformers added to watcher")) }) Describe("with missing headers", func() { var ( db *postgres.DB - watcher shared.EventWatcher + w watcher.EventWatcher mockBlockChain fakes.MockBlockChain headerRepository repositories.HeaderRepository repository mocks.MockWatcherRepository @@ -118,27 +118,25 @@ var _ = Describe("EventWatcher", func() { Expect(err).NotTo(HaveOccurred()) repository = mocks.MockWatcherRepository{} - watcher = shared.NewEventWatcher(db, &mockBlockChain) + w = watcher.NewEventWatcher(db, &mockBlockChain) }) It("executes each transformer", func() { fakeTransformer := &mocks.MockTransformer{} - watcher.AddTransformers([]shared2.TransformerInitializer{fakeTransformer.FakeTransformerInitializer}) + w.AddTransformers([]transformer.TransformerInitializer{fakeTransformer.FakeTransformerInitializer}) repository.SetMissingHeaders([]core.Header{fakes.FakeHeader}) - err := watcher.Execute(constants.HeaderMissing) - + err := w.Execute(constants.HeaderMissing) Expect(err).NotTo(HaveOccurred()) Expect(fakeTransformer.ExecuteWasCalled).To(BeTrue()) }) It("returns an error if transformer returns an error", func() { fakeTransformer := &mocks.MockTransformer{ExecuteError: errors.New("Something bad happened")} - watcher.AddTransformers([]shared2.TransformerInitializer{fakeTransformer.FakeTransformerInitializer}) + w.AddTransformers([]transformer.TransformerInitializer{fakeTransformer.FakeTransformerInitializer}) repository.SetMissingHeaders([]core.Header{fakes.FakeHeader}) - err := watcher.Execute(constants.HeaderMissing) - + err := w.Execute(constants.HeaderMissing) Expect(err).To(HaveOccurred()) Expect(fakeTransformer.ExecuteWasCalled).To(BeFalse()) }) @@ -147,10 +145,10 @@ var _ = Describe("EventWatcher", func() { transformerA := &mocks.MockTransformer{} transformerB := &mocks.MockTransformer{} - configA := shared2.TransformerConfig{TransformerName: "transformerA", + configA := transformer.TransformerConfig{TransformerName: "transformerA", ContractAddresses: []string{"0x000000000000000000000000000000000000000A"}, Topic: "0xA"} - configB := shared2.TransformerConfig{TransformerName: "transformerB", + configB := transformer.TransformerConfig{TransformerName: "transformerB", ContractAddresses: []string{"0x000000000000000000000000000000000000000b"}, Topic: "0xB"} @@ -164,11 +162,11 @@ var _ = Describe("EventWatcher", func() { mockBlockChain.SetGetEthLogsWithCustomQueryReturnLogs([]types.Log{logA, logB}) repository.SetMissingHeaders([]core.Header{fakes.FakeHeader}) - watcher = shared.NewEventWatcher(db, &mockBlockChain) - watcher.AddTransformers([]shared2.TransformerInitializer{ + w = watcher.NewEventWatcher(db, &mockBlockChain) + w.AddTransformers([]transformer.TransformerInitializer{ transformerA.FakeTransformerInitializer, transformerB.FakeTransformerInitializer}) - err := watcher.Execute(constants.HeaderMissing) + err := w.Execute(constants.HeaderMissing) Expect(err).NotTo(HaveOccurred()) Expect(transformerA.PassedLogs).To(Equal([]types.Log{logA})) Expect(transformerB.PassedLogs).To(Equal([]types.Log{logB})) @@ -184,17 +182,17 @@ var _ = Describe("EventWatcher", func() { It("fetches logs for added transformers", func() { addresses := []string{"0xA", "0xB"} topic := "0x1" - fakeTransformer.SetTransformerConfig(shared2.TransformerConfig{ + fakeTransformer.SetTransformerConfig(transformer.TransformerConfig{ Topic: topic, ContractAddresses: addresses}) - watcher.AddTransformers([]shared2.TransformerInitializer{fakeTransformer.FakeTransformerInitializer}) + w.AddTransformers([]transformer.TransformerInitializer{fakeTransformer.FakeTransformerInitializer}) - err := watcher.Execute(constants.HeaderMissing) + err := w.Execute(constants.HeaderMissing) Expect(err).NotTo(HaveOccurred()) fakeHash := common.HexToHash(fakes.FakeHeader.Hash) mockBlockChain.AssertGetEthLogsWithCustomQueryCalledWith(ethereum.FilterQuery{ BlockHash: &fakeHash, - Addresses: shared2.HexStringsToAddresses(addresses), + Addresses: transformer.HexStringsToAddresses(addresses), Topics: [][]common.Hash{{common.HexToHash(topic)}}, }) }) @@ -203,8 +201,8 @@ var _ = Describe("EventWatcher", func() { fetcherError := errors.New("FetcherError") mockBlockChain.SetGetEthLogsWithCustomQueryErr(fetcherError) - watcher.AddTransformers([]shared2.TransformerInitializer{fakeTransformer.FakeTransformerInitializer}) - err := watcher.Execute(constants.HeaderMissing) + w.AddTransformers([]transformer.TransformerInitializer{fakeTransformer.FakeTransformerInitializer}) + err := w.Execute(constants.HeaderMissing) Expect(err).To(MatchError(fetcherError)) }) }) diff --git a/libraries/shared/shared_suite_test.go b/libraries/shared/watcher/watcher_suite_test.go similarity index 94% rename from libraries/shared/shared_suite_test.go rename to libraries/shared/watcher/watcher_suite_test.go index 3e3b5fcc..2425d502 100644 --- a/libraries/shared/shared_suite_test.go +++ b/libraries/shared/watcher/watcher_suite_test.go @@ -14,7 +14,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -package shared_test +package watcher_test import ( log "github.com/sirupsen/logrus" @@ -27,7 +27,7 @@ import ( func TestShared(t *testing.T) { RegisterFailHandler(Fail) - RunSpecs(t, "Shared Suite") + RunSpecs(t, "Shared Watcher Suite") } var _ = BeforeSuite(func() { diff --git a/pkg/autogen/config.go b/pkg/autogen/config.go new file mode 100644 index 00000000..ed81472e --- /dev/null +++ b/pkg/autogen/config.go @@ -0,0 +1,23 @@ +// VulcanizeDB +// Copyright © 2018 Vulcanize + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package autogen + +type Config struct { + Imports map[string]string // Map of import alias to import path + FilePath string + FileName string +} diff --git a/pkg/autogen/generator.go b/pkg/autogen/generator.go new file mode 100644 index 00000000..ca6c39ae --- /dev/null +++ b/pkg/autogen/generator.go @@ -0,0 +1,138 @@ +// VulcanizeDB +// Copyright © 2018 Vulcanize + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package autogen + +import ( + "errors" + "os" + "os/exec" + "path/filepath" + "strings" + + . "github.com/dave/jennifer/jen" + "github.com/mitchellh/go-homedir" +) + +type Generator interface { + GenerateTransformerPlugin() error +} + +type generator struct { + *Config +} + +func NewGenerator(config Config) *generator { + return &generator{ + Config: &config, + } +} + +func (g *generator) GenerateTransformerPlugin() error { + if g.Config == nil { + return errors.New("generator needs a config file") + } + if g.Config.FilePath == "" { + return errors.New("generator is missing file path") + } + if len(g.Config.Imports) < 1 { + return errors.New("generator needs to be configured with imports") + } + + // Create file path + goFile, soFile, err := GetPaths(*g.Config) + if err != nil { + return err + } + + // Clear previous .go and .so files if they exist + err = ClearFiles(goFile, soFile) + if err != nil { + return err + } + + // Begin code generation + f := NewFile("main") + f.HeaderComment("This exporter is generated to export the configured transformer initializers") + + // Import TransformerInitializers + f.ImportAlias("github.com/vulcanize/vulcanizedb/libraries/shared/transformer", "interface") + for alias, imp := range g.Config.Imports { + f.ImportAlias(imp, alias) + } + + // Collect TransformerInitializer names + importedInitializers := make([]Code, 0, len(g.Config.Imports)) + for _, path := range g.Config.Imports { + importedInitializers = append(importedInitializers, Qual(path, "TransformerInitializer")) + } + + // Create Exporter variable with method to export a set of the configured TransformerInitializers + f.Type().Id("exporter").String() + f.Var().Id("Exporter").Id("exporter") + f.Func().Params( + Id("e").Id("exporter"), + ).Id("Export").Params().Index().Qual( + "github.com/vulcanize/vulcanizedb/libraries/shared/transformer", + "TransformerInitializer").Block( + Return(Index().Qual( + "github.com/vulcanize/vulcanizedb/libraries/shared/transformer", + "TransformerInitializer").Values(importedInitializers...))) + + // Write code to destination file + err = f.Save(goFile) + if err != nil { + return err + } + + // Build the .go file into a .so plugin + return exec.Command("go", "build", "-buildmode=plugin", "-o", soFile, goFile).Run() +} + +func GetPaths(config Config) (string, string, error) { + path, err := homedir.Expand(filepath.Clean(config.FilePath)) + if err != nil { + return "", "", err + } + if strings.Contains(path, "$GOPATH") { + env := os.Getenv("GOPATH") + spl := strings.Split(path, "$GOPATH")[1] + path = filepath.Join(env, spl) + } + + name := strings.Split(config.FileName, ".")[0] + goFile := filepath.Join(path, name+".go") + soFile := filepath.Join(path, name+".so") + + return goFile, soFile, nil +} + +func ClearFiles(files ...string) error { + for _, file := range files { + if _, err := os.Stat(file); err == nil { + err = os.Remove(file) + if err != nil { + return err + } + } else if os.IsNotExist(err) { + // fall through + } else { + return err + } + } + + return nil +} diff --git a/pkg/autogen/generator_suite_test.go b/pkg/autogen/generator_suite_test.go new file mode 100644 index 00000000..3ebcedca --- /dev/null +++ b/pkg/autogen/generator_suite_test.go @@ -0,0 +1,35 @@ +// VulcanizeDB +// Copyright © 2018 Vulcanize + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package autogen_test + +import ( + "io/ioutil" + "log" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestRepository(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Autogen Suite Test") +} + +var _ = BeforeSuite(func() { + log.SetOutput(ioutil.Discard) +}) diff --git a/pkg/autogen/generator_test.go b/pkg/autogen/generator_test.go new file mode 100644 index 00000000..bc60d980 --- /dev/null +++ b/pkg/autogen/generator_test.go @@ -0,0 +1,138 @@ +// VulcanizeDB +// Copyright © 2018 Vulcanize + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. + +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package autogen_test + +import ( + "plugin" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/spf13/viper" + + "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" + "github.com/vulcanize/vulcanizedb/libraries/shared/watcher" + "github.com/vulcanize/vulcanizedb/pkg/autogen" + "github.com/vulcanize/vulcanizedb/pkg/autogen/test_helpers" + "github.com/vulcanize/vulcanizedb/pkg/core" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories" + "github.com/vulcanize/vulcanizedb/pkg/transformers/bite" +) + +var testConfig = autogen.Config{ + Imports: map[string]string{ + "bite": "github.com/vulcanize/vulcanizedb/pkg/autogen/test_helpers/bite", + "deal": "github.com/vulcanize/vulcanizedb/pkg/autogen/test_helpers/deal", + }, + FileName: "testTransformerSet", + FilePath: "$GOPATH/src/github.com/vulcanize/vulcanizedb/pkg/autogen/test_helpers/test/", +} + +var targetConfig = autogen.Config{ + Imports: map[string]string{ + "bite": "github.com/vulcanize/vulcanizedb/pkg/autogen/test_helpers/bite", + "deal": "github.com/vulcanize/vulcanizedb/pkg/autogen/test_helpers/deal", + }, + FileName: "targetTransformerSet", + FilePath: "$GOPATH/src/github.com/vulcanize/vulcanizedb/pkg/autogen/test_helpers/target/", +} + +type Exporter interface { + Export() []transformer.TransformerInitializer +} + +var _ = Describe("Generator test", func() { + var g autogen.Generator + var goPath, soPath string + var err error + var bc core.BlockChain + var db *postgres.DB + var hr repositories.HeaderRepository + var headerID int64 + viper.SetConfigName("compose") + viper.AddConfigPath("$GOPATH/src/github.com/vulcanize/vulcanizedb/environments/") + + BeforeEach(func() { + goPath, soPath, err = autogen.GetPaths(testConfig) + Expect(err).ToNot(HaveOccurred()) + g = autogen.NewGenerator(testConfig) + err = g.GenerateTransformerPlugin() + Expect(err).ToNot(HaveOccurred()) + }) + + AfterEach(func() { + err := autogen.ClearFiles(goPath, soPath) + Expect(err).ToNot(HaveOccurred()) + }) + + Describe("GenerateTransformerPlugin", func() { + It("It bundles the specified transformer initializers into a Exporter object and creates .so", func() { + plug, err := plugin.Open(soPath) + Expect(err).ToNot(HaveOccurred()) + symExporter, err := plug.Lookup("Exporter") + Expect(err).ToNot(HaveOccurred()) + exporter, ok := symExporter.(Exporter) + Expect(ok).To(Equal(true)) + initializers := exporter.Export() + Expect(len(initializers)).To(Equal(2)) + }) + + It("Loads our generated Exporter and uses it to import an arbitrary set of TransformerInitializers that we can execute over", func() { + db, bc = test_helpers.SetupDBandBC() + defer test_helpers.TearDown(db) + + hr = repositories.NewHeaderRepository(db) + header1, err := bc.GetHeaderByNumber(9377319) + Expect(err).ToNot(HaveOccurred()) + headerID, err = hr.CreateOrUpdateHeader(header1) + Expect(err).ToNot(HaveOccurred()) + + plug, err := plugin.Open(soPath) + Expect(err).ToNot(HaveOccurred()) + symExporter, err := plug.Lookup("Exporter") + Expect(err).ToNot(HaveOccurred()) + exporter, ok := symExporter.(Exporter) + Expect(ok).To(Equal(true)) + initializers := exporter.Export() + + w := watcher.NewWatcher(db, bc) + w.AddTransformers(initializers) + err = w.Execute() + Expect(err).ToNot(HaveOccurred()) + + type model struct { + bite.BiteModel + Id int64 `db:"id"` + HeaderId int64 `db:"header_id"` + } + + returned := model{} + + err = db.Get(&returned, `SELECT * FROM maker.bite WHERE header_id = $1`, headerID) + Expect(err).ToNot(HaveOccurred()) + Expect(returned.Ilk).To(Equal("ETH")) + Expect(returned.Urn).To(Equal("0x0000d8b4147eDa80Fec7122AE16DA2479Cbd7ffB")) + Expect(returned.Ink).To(Equal("80000000000000000000")) + Expect(returned.Art).To(Equal("11000000000000000000000")) + Expect(returned.IArt).To(Equal("12496609999999999999992")) + Expect(returned.Tab).To(Equal("11000000000000000000000")) + Expect(returned.NFlip).To(Equal("7")) + Expect(returned.TransactionIndex).To(Equal(uint(1))) + Expect(returned.LogIndex).To(Equal(uint(4))) + }) + }) +}) diff --git a/pkg/autogen/test_helpers/bite/initializer.go b/pkg/autogen/test_helpers/bite/initializer.go new file mode 100644 index 00000000..1ce446dd --- /dev/null +++ b/pkg/autogen/test_helpers/bite/initializer.go @@ -0,0 +1,8 @@ +package bite + +import ( + "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" + "github.com/vulcanize/vulcanizedb/pkg/transformers" +) + +var TransformerInitializer transformer.TransformerInitializer = transformers.GetBiteTransformer().NewTransformer diff --git a/pkg/autogen/test_helpers/database.go b/pkg/autogen/test_helpers/database.go new file mode 100644 index 00000000..66d6cc0e --- /dev/null +++ b/pkg/autogen/test_helpers/database.go @@ -0,0 +1,65 @@ +package test_helpers + +import ( + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" + . "github.com/onsi/gomega" + + "github.com/vulcanize/vulcanizedb/pkg/config" + "github.com/vulcanize/vulcanizedb/pkg/core" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/geth" + "github.com/vulcanize/vulcanizedb/pkg/geth/client" + rpc2 "github.com/vulcanize/vulcanizedb/pkg/geth/converters/rpc" + "github.com/vulcanize/vulcanizedb/pkg/geth/node" +) + +func SetupDBandBC() (*postgres.DB, core.BlockChain) { + infuraIPC := "http://kovan0.vulcanize.io:8545" + rawRpcClient, err := rpc.Dial(infuraIPC) + Expect(err).NotTo(HaveOccurred()) + rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC) + ethClient := ethclient.NewClient(rawRpcClient) + blockChainClient := client.NewEthClient(ethClient) + node := node.MakeNode(rpcClient) + transactionConverter := rpc2.NewRpcTransactionConverter(ethClient) + blockChain := geth.NewBlockChain(blockChainClient, rpcClient, node, transactionConverter) + + db, err := postgres.NewDB(config.Database{ + Hostname: "localhost", + Name: "vulcanize_private", + Port: 5432, + }, blockChain.Node()) + Expect(err).NotTo(HaveOccurred()) + + return db, blockChain +} + +func TearDown(db *postgres.DB) { + tx, err := db.Begin() + Expect(err).NotTo(HaveOccurred()) + + _, err = tx.Exec(`DELETE FROM headers`) + Expect(err).NotTo(HaveOccurred()) + + _, err = tx.Exec(`DELETE FROM logs`) + Expect(err).NotTo(HaveOccurred()) + + _, err = tx.Exec(`DELETE FROM log_filters`) + Expect(err).NotTo(HaveOccurred()) + + _, err = tx.Exec(`DELETE FROM transactions`) + Expect(err).NotTo(HaveOccurred()) + + _, err = tx.Exec(`DELETE FROM receipts`) + Expect(err).NotTo(HaveOccurred()) + + _, err = tx.Exec(`DELETE FROM checked_headers`) + Expect(err).NotTo(HaveOccurred()) + + _, err = tx.Exec(`DELETE FROM maker.bite`) + Expect(err).NotTo(HaveOccurred()) + + err = tx.Commit() + Expect(err).NotTo(HaveOccurred()) +} diff --git a/pkg/autogen/test_helpers/deal/initializer.go b/pkg/autogen/test_helpers/deal/initializer.go new file mode 100644 index 00000000..84a44263 --- /dev/null +++ b/pkg/autogen/test_helpers/deal/initializer.go @@ -0,0 +1,8 @@ +package deal + +import ( + "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" + "github.com/vulcanize/vulcanizedb/pkg/transformers" +) + +var TransformerInitializer transformer.TransformerInitializer = transformers.GetDealTransformer().NewLogNoteTransformer diff --git a/pkg/autogen/test_helpers/test/README.md b/pkg/autogen/test_helpers/test/README.md new file mode 100644 index 00000000..6a93702e --- /dev/null +++ b/pkg/autogen/test_helpers/test/README.md @@ -0,0 +1,3 @@ +### Test + +This empty directory is for holding the output code generated, and then deleted, during the generator_tests \ No newline at end of file diff --git a/pkg/omni/full/transformer/transformer_test.go b/pkg/omni/full/transformer/transformer_test.go index 9d68143c..171b1618 100644 --- a/pkg/omni/full/transformer/transformer_test.go +++ b/pkg/omni/full/transformer/transformer_test.go @@ -324,7 +324,7 @@ var _ = Describe("Transformer", func() { Expect(res.Address).To(Equal("0x0000000000000000000000000000000000000000")) Expect(res.TokenName).To(Equal("")) - err = db.QueryRowx(fmt.Sprintf("SELECT * FROM full_%s.owner_method WHERE node_ = '0x95832c7a47ff8a7840e28b78ceMADEUPaaf4HASHc186badTHIS288IS625bFAKE' AND block = '6194636'", ensAddr)).StructScan(&res) + err = db.QueryRowx(fmt.Sprintf("SELECT * FROM full_%s.owner_method WHERE node_ = '0x95832c7a47ff8a7840e28b78ceMADEUPaaf4HASHc186badTHItransformers.8IS625bFAKE' AND block = '6194636'", ensAddr)).StructScan(&res) Expect(err).To(HaveOccurred()) }) diff --git a/pkg/omni/light/transformer/transformer_test.go b/pkg/omni/light/transformer/transformer_test.go index db805532..a5c69515 100644 --- a/pkg/omni/light/transformer/transformer_test.go +++ b/pkg/omni/light/transformer/transformer_test.go @@ -331,7 +331,7 @@ var _ = Describe("Transformer", func() { Expect(res.Address).To(Equal("0x0000000000000000000000000000000000000000")) Expect(res.TokenName).To(Equal("")) - err = db.QueryRowx(fmt.Sprintf("SELECT * FROM light_%s.owner_method WHERE node_ = '0x95832c7a47ff8a7840e28b78ceMADEUPaaf4HASHc186badTHIS288IS625bFAKE' AND block = '6885696'", ensAddr)).StructScan(&res) + err = db.QueryRowx(fmt.Sprintf("SELECT * FROM light_%s.owner_method WHERE node_ = '0x95832c7a47ff8a7840e28b78ceMADEUPaaf4HASHc186badTHItransformers.8IS625bFAKE' AND block = '6885696'", ensAddr)).StructScan(&res) Expect(err).To(HaveOccurred()) }) @@ -491,7 +491,7 @@ var _ = Describe("Transformer", func() { Expect(owner.Address).To(Equal("0x0000000000000000000000000000000000000000")) Expect(owner.TokenName).To(Equal("")) - err = db.QueryRowx(fmt.Sprintf("SELECT * FROM light_%s.owner_method WHERE node_ = '0x95832c7a47ff8a7840e28b78ceMADEUPaaf4HASHc186badTHIS288IS625bFAKE' AND block = '6885696'", ensAddr)).StructScan(&owner) + err = db.QueryRowx(fmt.Sprintf("SELECT * FROM light_%s.owner_method WHERE node_ = '0x95832c7a47ff8a7840e28b78ceMADEUPaaf4HASHc186badTHItransformers.8IS625bFAKE' AND block = '6885696'", ensAddr)).StructScan(&owner) Expect(err).To(HaveOccurred()) bal := test_helpers.BalanceOf{} diff --git a/pkg/transformers/bite/config.go b/pkg/transformers/bite/config.go index e6fcff04..c965f212 100644 --- a/pkg/transformers/bite/config.go +++ b/pkg/transformers/bite/config.go @@ -17,12 +17,12 @@ package bite import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetBiteConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetBiteConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.BiteLabel, ContractAddresses: []string{constants.CatContractAddress()}, ContractAbi: constants.CatABI(), diff --git a/pkg/transformers/cat_file/chop_lump/config.go b/pkg/transformers/cat_file/chop_lump/config.go index 01c32106..8398b16e 100644 --- a/pkg/transformers/cat_file/chop_lump/config.go +++ b/pkg/transformers/cat_file/chop_lump/config.go @@ -17,12 +17,12 @@ package chop_lump import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetCatFileChopLumpConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetCatFileChopLumpConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.CatFileChopLumpLabel, ContractAddresses: []string{constants.CatContractAddress()}, ContractAbi: constants.CatABI(), diff --git a/pkg/transformers/cat_file/flip/config.go b/pkg/transformers/cat_file/flip/config.go index f8401d2d..b8e010fc 100644 --- a/pkg/transformers/cat_file/flip/config.go +++ b/pkg/transformers/cat_file/flip/config.go @@ -17,12 +17,12 @@ package flip import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetCatFileFlipConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetCatFileFlipConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.CatFileFlipLabel, ContractAddresses: []string{constants.CatContractAddress()}, ContractAbi: constants.CatABI(), diff --git a/pkg/transformers/cat_file/pit_vow/config.go b/pkg/transformers/cat_file/pit_vow/config.go index 4db102a5..8db450b9 100644 --- a/pkg/transformers/cat_file/pit_vow/config.go +++ b/pkg/transformers/cat_file/pit_vow/config.go @@ -17,12 +17,12 @@ package pit_vow import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetCatFilePitVowConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetCatFilePitVowConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.CatFilePitVowLabel, ContractAddresses: []string{constants.CatContractAddress()}, ContractAbi: constants.CatABI(), diff --git a/pkg/transformers/deal/config.go b/pkg/transformers/deal/config.go index f9f77f77..398a1738 100644 --- a/pkg/transformers/deal/config.go +++ b/pkg/transformers/deal/config.go @@ -17,12 +17,13 @@ package deal import ( + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetDealConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetDealConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.DealLabel, ContractAddresses: []string{constants.FlapperContractAddress(), constants.FlipperContractAddress(), constants.FlopperContractAddress()}, ContractAbi: constants.FlipperABI(), diff --git a/pkg/transformers/dent/config.go b/pkg/transformers/dent/config.go index c6703946..e1cd5cfd 100644 --- a/pkg/transformers/dent/config.go +++ b/pkg/transformers/dent/config.go @@ -17,12 +17,13 @@ package dent import ( + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetDentConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetDentConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.DentLabel, ContractAddresses: []string{constants.FlipperContractAddress(), constants.FlopperContractAddress()}, ContractAbi: constants.FlipperABI(), diff --git a/pkg/transformers/drip_drip/config.go b/pkg/transformers/drip_drip/config.go index 6ad1921f..4411ce03 100644 --- a/pkg/transformers/drip_drip/config.go +++ b/pkg/transformers/drip_drip/config.go @@ -17,12 +17,12 @@ package drip_drip import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetDripDripConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetDripDripConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ ContractAddresses: []string{constants.DripContractAddress()}, ContractAbi: constants.DripABI(), Topic: constants.GetDripDripSignature(), diff --git a/pkg/transformers/drip_file/ilk/config.go b/pkg/transformers/drip_file/ilk/config.go index 1ada59ba..ffb202e5 100644 --- a/pkg/transformers/drip_file/ilk/config.go +++ b/pkg/transformers/drip_file/ilk/config.go @@ -17,12 +17,12 @@ package ilk import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetDripFileIlkConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetDripFileIlkConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.DripFileIlkLabel, ContractAddresses: []string{constants.DripContractAddress()}, ContractAbi: constants.DripABI(), diff --git a/pkg/transformers/drip_file/repo/config.go b/pkg/transformers/drip_file/repo/config.go index ecbf0e3f..56ec6248 100644 --- a/pkg/transformers/drip_file/repo/config.go +++ b/pkg/transformers/drip_file/repo/config.go @@ -17,12 +17,12 @@ package repo import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetDripFileRepoConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetDripFileRepoConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.DripFileRepoLabel, ContractAddresses: []string{constants.DripContractAddress()}, ContractAbi: constants.DripABI(), diff --git a/pkg/transformers/drip_file/vow/config.go b/pkg/transformers/drip_file/vow/config.go index e296bb09..9910a149 100644 --- a/pkg/transformers/drip_file/vow/config.go +++ b/pkg/transformers/drip_file/vow/config.go @@ -17,12 +17,12 @@ package vow import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetDripFileVowConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetDripFileVowConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.DripFileVowLabel, ContractAddresses: []string{constants.DripContractAddress()}, ContractAbi: constants.DripABI(), diff --git a/pkg/transformers/factories/log_note_transformer.go b/pkg/transformers/factories/log_note_transformer.go index c22c5a42..08092b8c 100644 --- a/pkg/transformers/factories/log_note_transformer.go +++ b/pkg/transformers/factories/log_note_transformer.go @@ -20,19 +20,19 @@ import ( "github.com/ethereum/go-ethereum/core/types" log "github.com/sirupsen/logrus" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) type LogNoteTransformer struct { - Config shared.TransformerConfig + Config shared_t.TransformerConfig Converter LogNoteConverter Repository Repository } -func (transformer LogNoteTransformer) NewLogNoteTransformer(db *postgres.DB) shared.Transformer { +func (transformer LogNoteTransformer) NewLogNoteTransformer(db *postgres.DB) shared_t.Transformer { transformer.Repository.SetDB(db) return transformer } @@ -68,6 +68,6 @@ func (transformer LogNoteTransformer) GetName() string { return transformer.Config.TransformerName } -func (transformer LogNoteTransformer) GetConfig() shared.TransformerConfig { +func (transformer LogNoteTransformer) GetConfig() shared_t.TransformerConfig { return transformer.Config } diff --git a/pkg/transformers/factories/log_note_transformer_test.go b/pkg/transformers/factories/log_note_transformer_test.go index 851472f8..fa35624f 100644 --- a/pkg/transformers/factories/log_note_transformer_test.go +++ b/pkg/transformers/factories/log_note_transformer_test.go @@ -17,17 +17,19 @@ package factories_test import ( + "math/rand" + "github.com/ethereum/go-ethereum/core/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/fakes" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks" - "math/rand" ) var _ = Describe("LogNoteTransformer", func() { @@ -35,7 +37,7 @@ var _ = Describe("LogNoteTransformer", func() { repository mocks.MockRepository converter mocks.MockLogNoteConverter headerOne core.Header - transformer shared.Transformer + transformer shared_t.Transformer model test_data.GenericModel config = test_data.GenericTestConfig logs = test_data.GenericTestLogs diff --git a/pkg/transformers/factories/transformer.go b/pkg/transformers/factories/transformer.go index cca34a66..9ed98e77 100644 --- a/pkg/transformers/factories/transformer.go +++ b/pkg/transformers/factories/transformer.go @@ -20,19 +20,19 @@ import ( "github.com/ethereum/go-ethereum/core/types" log "github.com/sirupsen/logrus" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) type Transformer struct { - Config shared.TransformerConfig + Config shared_t.TransformerConfig Converter Converter Repository Repository } -func (transformer Transformer) NewTransformer(db *postgres.DB) shared.Transformer { +func (transformer Transformer) NewTransformer(db *postgres.DB) shared_t.Transformer { transformer.Repository.SetDB(db) return transformer } @@ -75,6 +75,6 @@ func (transformer Transformer) GetName() string { return transformer.Config.TransformerName } -func (transformer Transformer) GetConfig() shared.TransformerConfig { +func (transformer Transformer) GetConfig() shared_t.TransformerConfig { return transformer.Config } diff --git a/pkg/transformers/factories/transformer_test.go b/pkg/transformers/factories/transformer_test.go index 3f8c0039..ce5ffc98 100644 --- a/pkg/transformers/factories/transformer_test.go +++ b/pkg/transformers/factories/transformer_test.go @@ -17,24 +17,26 @@ package factories_test import ( + "math/rand" + "github.com/ethereum/go-ethereum/core/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/fakes" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks" - "math/rand" ) var _ = Describe("Transformer", func() { var ( repository mocks.MockRepository converter mocks.MockConverter - transformer shared.Transformer + transformer shared_t.Transformer headerOne core.Header config = test_data.GenericTestConfig logs = test_data.GenericTestLogs diff --git a/pkg/transformers/flap_kick/config.go b/pkg/transformers/flap_kick/config.go index 70c5b7c9..914d86d8 100644 --- a/pkg/transformers/flap_kick/config.go +++ b/pkg/transformers/flap_kick/config.go @@ -17,12 +17,12 @@ package flap_kick import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetFlapKickConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetFlapKickConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.FlapKickLabel, ContractAddresses: []string{constants.FlapperContractAddress()}, ContractAbi: constants.FlapperABI(), diff --git a/pkg/transformers/flip_kick/config.go b/pkg/transformers/flip_kick/config.go index 7fa8d908..63e786be 100644 --- a/pkg/transformers/flip_kick/config.go +++ b/pkg/transformers/flip_kick/config.go @@ -17,12 +17,12 @@ package flip_kick import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetFlipKickConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetFlipKickConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.FlipKickLabel, ContractAddresses: []string{constants.FlipperContractAddress()}, ContractAbi: constants.FlipperABI(), diff --git a/pkg/transformers/flop_kick/config.go b/pkg/transformers/flop_kick/config.go index 5356dbe3..c3f3c5bc 100644 --- a/pkg/transformers/flop_kick/config.go +++ b/pkg/transformers/flop_kick/config.go @@ -17,12 +17,12 @@ package flop_kick import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetFlopKickConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetFlopKickConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.FlopKickLabel, ContractAddresses: []string{constants.FlopperContractAddress()}, ContractAbi: constants.FlopperABI(), diff --git a/pkg/transformers/frob/config.go b/pkg/transformers/frob/config.go index 5c91231a..3499d39d 100644 --- a/pkg/transformers/frob/config.go +++ b/pkg/transformers/frob/config.go @@ -17,12 +17,12 @@ package frob import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetFrobConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetFrobConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.FrobLabel, ContractAddresses: []string{constants.PitContractAddress()}, ContractAbi: constants.PitABI(), diff --git a/pkg/transformers/integration_tests/bite.go b/pkg/transformers/integration_tests/bite.go index 28c1cb8c..9ebd3c67 100644 --- a/pkg/transformers/integration_tests/bite.go +++ b/pkg/transformers/integration_tests/bite.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/geth" "github.com/vulcanize/vulcanizedb/pkg/transformers/bite" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" @@ -33,7 +34,7 @@ import ( "github.com/vulcanize/vulcanizedb/test_config" ) -var testBiteConfig = shared.TransformerConfig{ +var testBiteConfig = shared_t.TransformerConfig{ TransformerName: constants.BiteLabel, ContractAddresses: []string{test_data.KovanCatContractAddress}, ContractAbi: test_data.KovanCatABI, diff --git a/pkg/transformers/integration_tests/cat_file.go b/pkg/transformers/integration_tests/cat_file.go index 48ce0c37..8657422d 100644 --- a/pkg/transformers/integration_tests/cat_file.go +++ b/pkg/transformers/integration_tests/cat_file.go @@ -29,6 +29,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/geth/client" @@ -66,7 +67,7 @@ var _ = Describe("Cat File transformer", func() { header, err := persistHeader(db, chopLumpBlockNumber, blockChain) Expect(err).NotTo(HaveOccurred()) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.CatFileChopLumpLabel, ContractAddresses: []string{test_data.KovanCatContractAddress}, ContractAbi: test_data.KovanCatABI, @@ -162,7 +163,7 @@ var _ = Describe("Cat File transformer", func() { header, err := persistHeader(db, flipBlockNumber, blockChain) Expect(err).NotTo(HaveOccurred()) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.CatFileFlipLabel, ContractAddresses: []string{test_data.KovanCatContractAddress}, ContractAbi: test_data.KovanCatABI, @@ -250,7 +251,7 @@ var _ = Describe("Cat File transformer", func() { header, err := persistHeader(db, pitVowBlockNumber, blockChain) Expect(err).NotTo(HaveOccurred()) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.CatFilePitVowLabel, ContractAddresses: []string{test_data.KovanCatContractAddress}, ContractAbi: test_data.KovanCatABI, diff --git a/pkg/transformers/integration_tests/deal.go b/pkg/transformers/integration_tests/deal.go index 8e8a6908..c8a7f361 100644 --- a/pkg/transformers/integration_tests/deal.go +++ b/pkg/transformers/integration_tests/deal.go @@ -23,6 +23,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/transformers/deal" @@ -35,7 +36,7 @@ var _ = Describe("Deal transformer", func() { var ( db *postgres.DB blockChain core.BlockChain - config shared.TransformerConfig + config shared_t.TransformerConfig initializer factories.LogNoteTransformer fetcher *shared.Fetcher addresses []common.Address @@ -50,7 +51,7 @@ var _ = Describe("Deal transformer", func() { db = test_config.NewTestDB(blockChain.Node()) test_config.CleanTestDB(db) - config = shared.TransformerConfig{ + config = shared_t.TransformerConfig{ TransformerName: constants.DealLabel, ContractAddresses: []string{test_data.KovanFlapperContractAddress, test_data.KovanFlipperContractAddress, test_data.KovanFlopperContractAddress}, ContractAbi: test_data.KovanFlipperABI, @@ -66,7 +67,7 @@ var _ = Describe("Deal transformer", func() { } fetcher = shared.NewFetcher(blockChain) - addresses = shared.HexStringsToAddresses(config.ContractAddresses) + addresses = shared_t.HexStringsToAddresses(config.ContractAddresses) topics = []common.Hash{common.HexToHash(config.Topic)} }) diff --git a/pkg/transformers/integration_tests/dent.go b/pkg/transformers/integration_tests/dent.go index aa12143a..70c1aaf0 100644 --- a/pkg/transformers/integration_tests/dent.go +++ b/pkg/transformers/integration_tests/dent.go @@ -7,6 +7,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/transformers/dent" @@ -20,8 +21,8 @@ var _ = Describe("Dent transformer", func() { db *postgres.DB blockChain core.BlockChain fetcher *shared.Fetcher - transformer shared.Transformer - config shared.TransformerConfig + transformer shared_t.Transformer + config shared_t.TransformerConfig addresses []common.Address topics []common.Hash initializer factories.LogNoteTransformer @@ -35,7 +36,7 @@ var _ = Describe("Dent transformer", func() { db = test_config.NewTestDB(blockChain.Node()) test_config.CleanTestDB(db) - config = shared.TransformerConfig{ + config = shared_t.TransformerConfig{ TransformerName: constants.DentLabel, ContractAddresses: []string{test_data.KovanFlipperContractAddress, test_data.KovanFlopperContractAddress}, ContractAbi: test_data.KovanFlipperABI, @@ -44,7 +45,7 @@ var _ = Describe("Dent transformer", func() { EndingBlockNumber: -1, } - addresses = shared.HexStringsToAddresses(config.ContractAddresses) + addresses = shared_t.HexStringsToAddresses(config.ContractAddresses) topics = []common.Hash{common.HexToHash(config.Topic)} fetcher = shared.NewFetcher(blockChain) diff --git a/pkg/transformers/integration_tests/drip_drip.go b/pkg/transformers/integration_tests/drip_drip.go index f369a529..ee747542 100644 --- a/pkg/transformers/integration_tests/drip_drip.go +++ b/pkg/transformers/integration_tests/drip_drip.go @@ -20,14 +20,16 @@ import ( "github.com/ethereum/go-ethereum/common" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_drip" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "strconv" - "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_drip" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/test_config" ) @@ -36,7 +38,7 @@ var _ = Describe("DripDrip Transformer", func() { var ( db *postgres.DB blockChain core.BlockChain - config shared.TransformerConfig + config shared_t.TransformerConfig ) BeforeEach(func() { @@ -47,7 +49,7 @@ var _ = Describe("DripDrip Transformer", func() { db = test_config.NewTestDB(blockChain.Node()) test_config.CleanTestDB(db) - config = shared.TransformerConfig{ + config = shared_t.TransformerConfig{ ContractAddresses: []string{test_data.KovanDripContractAddress}, ContractAbi: test_data.KovanDripABI, Topic: test_data.KovanDripDripSignature, @@ -73,7 +75,7 @@ var _ = Describe("DripDrip Transformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) @@ -109,7 +111,7 @@ var _ = Describe("DripDrip Transformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/drip_file_vow.go b/pkg/transformers/integration_tests/drip_file_vow.go index 459e33eb..3e522444 100644 --- a/pkg/transformers/integration_tests/drip_file_vow.go +++ b/pkg/transformers/integration_tests/drip_file_vow.go @@ -20,13 +20,15 @@ import ( "github.com/ethereum/go-ethereum/common" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/vow" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" - "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/vow" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/test_config" ) @@ -48,7 +50,7 @@ var _ = Describe("Drip File Vow LogNoteTransformer", func() { It("transforms DripFileVow log events", func() { blockNumber := int64(8762197) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.DripFileVowLabel, ContractAddresses: []string{test_data.KovanDripContractAddress}, ContractAbi: test_data.KovanDripABI, @@ -69,7 +71,7 @@ var _ = Describe("Drip File Vow LogNoteTransformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) @@ -88,7 +90,7 @@ var _ = Describe("Drip File Vow LogNoteTransformer", func() { It("rechecks drip file vow event", func() { blockNumber := int64(8762197) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.DripFileVowLabel, ContractAddresses: []string{test_data.KovanDripContractAddress}, ContractAbi: test_data.KovanDripABI, @@ -109,7 +111,7 @@ var _ = Describe("Drip File Vow LogNoteTransformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/flap_kick.go b/pkg/transformers/integration_tests/flap_kick.go index 4aecc055..f8803533 100644 --- a/pkg/transformers/integration_tests/flap_kick.go +++ b/pkg/transformers/integration_tests/flap_kick.go @@ -27,6 +27,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/flap_kick" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" @@ -50,7 +51,7 @@ var _ = Describe("FlapKick Transformer", func() { It("fetches and transforms a FlapKick event from Kovan chain", func() { blockNumber := int64(9002933) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.FlapKickLabel, ContractAddresses: []string{test_data.KovanFlapperContractAddress}, ContractAbi: test_data.KovanFlapperABI, @@ -70,7 +71,7 @@ var _ = Describe("FlapKick Transformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/flip_kick.go b/pkg/transformers/integration_tests/flip_kick.go index 0068db7a..d062faea 100644 --- a/pkg/transformers/integration_tests/flip_kick.go +++ b/pkg/transformers/integration_tests/flip_kick.go @@ -24,6 +24,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/geth" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/flip_kick" @@ -59,7 +60,7 @@ var _ = Describe("FlipKick Transformer", func() { It("fetches and transforms a FlipKick event from Kovan chain", func() { blockNumber := int64(8956476) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.FlipKickLabel, ContractAddresses: []string{test_data.KovanFlipperContractAddress}, ContractAbi: test_data.KovanFlipperABI, @@ -86,7 +87,7 @@ var _ = Describe("FlipKick Transformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/flop_kick.go b/pkg/transformers/integration_tests/flop_kick.go index 78e26751..7d73217f 100644 --- a/pkg/transformers/integration_tests/flop_kick.go +++ b/pkg/transformers/integration_tests/flop_kick.go @@ -24,6 +24,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/geth" @@ -39,7 +40,7 @@ var _ = Describe("FlopKick Transformer", func() { var ( db *postgres.DB blockChain core.BlockChain - config shared.TransformerConfig + config shared_t.TransformerConfig initializer factories.Transformer fetcher shared.LogFetcher addresses []common.Address @@ -54,7 +55,7 @@ var _ = Describe("FlopKick Transformer", func() { db = test_config.NewTestDB(blockChain.Node()) test_config.CleanTestDB(db) - config = shared.TransformerConfig{ + config = shared_t.TransformerConfig{ TransformerName: constants.FlopKickLabel, ContractAddresses: []string{test_data.KovanFlopperContractAddress}, ContractAbi: test_data.KovanFlopperABI, @@ -70,7 +71,7 @@ var _ = Describe("FlopKick Transformer", func() { } fetcher = shared.NewFetcher(blockChain) - addresses = shared.HexStringsToAddresses(config.ContractAddresses) + addresses = shared_t.HexStringsToAddresses(config.ContractAddresses) topics = []common.Hash{common.HexToHash(config.Topic)} }) diff --git a/pkg/transformers/integration_tests/frob.go b/pkg/transformers/integration_tests/frob.go index 43ef42d9..333f0b0c 100644 --- a/pkg/transformers/integration_tests/frob.go +++ b/pkg/transformers/integration_tests/frob.go @@ -23,6 +23,7 @@ import ( . "github.com/onsi/gomega" "strconv" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/geth" @@ -39,7 +40,7 @@ var _ = Describe("Frob Transformer", func() { db *postgres.DB blockChain core.BlockChain fetcher *shared.Fetcher - config shared.TransformerConfig + config shared_t.TransformerConfig initializer factories.Transformer ) @@ -52,7 +53,7 @@ var _ = Describe("Frob Transformer", func() { test_config.CleanTestDB(db) fetcher = shared.NewFetcher(blockChain) - config = shared.TransformerConfig{ + config = shared_t.TransformerConfig{ TransformerName: constants.FrobLabel, ContractAddresses: []string{test_data.KovanPitContractAddress}, ContractAbi: test_data.KovanPitABI, @@ -77,7 +78,7 @@ var _ = Describe("Frob Transformer", func() { Expect(err).NotTo(HaveOccurred()) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/pit_file_debt_ceiling.go b/pkg/transformers/integration_tests/pit_file_debt_ceiling.go index 94cf232d..19c49afb 100644 --- a/pkg/transformers/integration_tests/pit_file_debt_ceiling.go +++ b/pkg/transformers/integration_tests/pit_file_debt_ceiling.go @@ -27,6 +27,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/debt_ceiling" "github.com/vulcanize/vulcanizedb/test_config" ) @@ -48,7 +49,7 @@ var _ = Describe("PitFileDebtCeiling LogNoteTransformer", func() { It("fetches and transforms a PitFileDebtCeiling event from Kovan chain", func() { blockNumber := int64(8535578) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.PitFileDebtCeilingLabel, ContractAddresses: []string{test_data.KovanPitContractAddress}, ContractAbi: test_data.KovanPitABI, @@ -62,7 +63,7 @@ var _ = Describe("PitFileDebtCeiling LogNoteTransformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/pit_file_ilk.go b/pkg/transformers/integration_tests/pit_file_ilk.go index 9c8c221c..7d35f6a5 100644 --- a/pkg/transformers/integration_tests/pit_file_ilk.go +++ b/pkg/transformers/integration_tests/pit_file_ilk.go @@ -26,6 +26,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "strconv" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/ilk" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" @@ -48,7 +49,7 @@ var _ = Describe("PitFileIlk LogNoteTransformer", func() { Expect(err).NotTo(HaveOccurred()) db = test_config.NewTestDB(blockChain.Node()) test_config.CleanTestDB(db) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.PitFileIlkLabel, ContractAddresses: []string{test_data.KovanPitContractAddress}, ContractAbi: test_data.KovanPitABI, @@ -57,7 +58,7 @@ var _ = Describe("PitFileIlk LogNoteTransformer", func() { EndingBlockNumber: -1, } - addresses = shared.HexStringsToAddresses(config.ContractAddresses) + addresses = shared_t.HexStringsToAddresses(config.ContractAddresses) topics = []common.Hash{common.HexToHash(config.Topic)} initializer = factories.LogNoteTransformer{ diff --git a/pkg/transformers/integration_tests/price_feeds.go b/pkg/transformers/integration_tests/price_feeds.go index 7bb27945..43ce7bd2 100644 --- a/pkg/transformers/integration_tests/price_feeds.go +++ b/pkg/transformers/integration_tests/price_feeds.go @@ -9,6 +9,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" @@ -21,7 +22,7 @@ var _ = Describe("Price feeds transformer", func() { var ( db *postgres.DB blockChain core.BlockChain - config shared.TransformerConfig + config shared_t.TransformerConfig fetcher *shared.Fetcher initializer factories.LogNoteTransformer topics []common.Hash @@ -35,7 +36,7 @@ var _ = Describe("Price feeds transformer", func() { db = test_config.NewTestDB(blockChain.Node()) test_config.CleanTestDB(db) - config = shared.TransformerConfig{ + config = shared_t.TransformerConfig{ TransformerName: constants.PriceFeedLabel, ContractAddresses: []string{ test_data.KovanPepContractAddress, @@ -69,7 +70,7 @@ var _ = Describe("Price feeds transformer", func() { initializer.Config.EndingBlockNumber = blockNumber logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(addresses), + shared_t.HexStringsToAddresses(addresses), topics, header) Expect(err).NotTo(HaveOccurred()) @@ -134,7 +135,7 @@ var _ = Describe("Price feeds transformer", func() { initializer.Config.EndingBlockNumber = blockNumber logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(addresses), + shared_t.HexStringsToAddresses(addresses), topics, header) Expect(err).NotTo(HaveOccurred()) @@ -160,7 +161,7 @@ var _ = Describe("Price feeds transformer", func() { initializer.Config.EndingBlockNumber = blockNumber logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(addresses), + shared_t.HexStringsToAddresses(addresses), topics, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/tend.go b/pkg/transformers/integration_tests/tend.go index b621bc66..9555e663 100644 --- a/pkg/transformers/integration_tests/tend.go +++ b/pkg/transformers/integration_tests/tend.go @@ -20,6 +20,7 @@ import ( "github.com/ethereum/go-ethereum/common" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" @@ -34,7 +35,7 @@ var _ = Describe("Tend LogNoteTransformer", func() { var ( db *postgres.DB blockChain core.BlockChain - config shared.TransformerConfig + config shared_t.TransformerConfig fetcher *shared.Fetcher initializer factories.LogNoteTransformer addresses []common.Address @@ -49,7 +50,7 @@ var _ = Describe("Tend LogNoteTransformer", func() { db = test_config.NewTestDB(blockChain.Node()) test_config.CleanTestDB(db) - config = shared.TransformerConfig{ + config = shared_t.TransformerConfig{ TransformerName: constants.TendLabel, ContractAddresses: []string{test_data.KovanFlapperContractAddress, test_data.KovanFlipperContractAddress}, ContractAbi: test_data.KovanFlipperABI, @@ -59,7 +60,7 @@ var _ = Describe("Tend LogNoteTransformer", func() { } fetcher = shared.NewFetcher(blockChain) - addresses = shared.HexStringsToAddresses(config.ContractAddresses) + addresses = shared_t.HexStringsToAddresses(config.ContractAddresses) topics = []common.Hash{common.HexToHash(config.Topic)} initializer = factories.LogNoteTransformer{ diff --git a/pkg/transformers/integration_tests/vat_flux.go b/pkg/transformers/integration_tests/vat_flux.go index f2bb9433..896688ea 100644 --- a/pkg/transformers/integration_tests/vat_flux.go +++ b/pkg/transformers/integration_tests/vat_flux.go @@ -24,6 +24,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "strconv" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_flux" @@ -33,7 +34,7 @@ import ( var _ = Describe("VatFlux LogNoteTransformer", func() { It("transforms VatFlux log events", func() { blockNumber := int64(9004474) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.VatFluxLabel, ContractAddresses: []string{test_data.KovanVatContractAddress}, ContractAbi: test_data.KovanVatABI, @@ -55,7 +56,7 @@ var _ = Describe("VatFlux LogNoteTransformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/vat_fold.go b/pkg/transformers/integration_tests/vat_fold.go index 39bb93f4..92e1ea12 100644 --- a/pkg/transformers/integration_tests/vat_fold.go +++ b/pkg/transformers/integration_tests/vat_fold.go @@ -27,6 +27,7 @@ import ( "github.com/vulcanize/vulcanizedb/test_config" "strconv" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_fold" @@ -49,7 +50,7 @@ var _ = Describe("VatFold Transformer", func() { It("transforms VatFold log events", func() { blockNumber := int64(9367233) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.VatFoldLabel, ContractAddresses: []string{test_data.KovanVatContractAddress}, ContractAbi: test_data.KovanVatABI, @@ -63,7 +64,7 @@ var _ = Describe("VatFold Transformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/vat_grab.go b/pkg/transformers/integration_tests/vat_grab.go index 19360710..07546ded 100644 --- a/pkg/transformers/integration_tests/vat_grab.go +++ b/pkg/transformers/integration_tests/vat_grab.go @@ -26,6 +26,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_grab" @@ -35,7 +36,7 @@ import ( var _ = Describe("Vat Grab Transformer", func() { It("transforms VatGrab log events", func() { blockNumber := int64(8958230) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.VatGrabLabel, ContractAddresses: []string{test_data.KovanVatContractAddress}, ContractAbi: test_data.KovanVatABI, @@ -57,7 +58,7 @@ var _ = Describe("Vat Grab Transformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/vat_heal.go b/pkg/transformers/integration_tests/vat_heal.go index e59b861f..54d0ab5c 100644 --- a/pkg/transformers/integration_tests/vat_heal.go +++ b/pkg/transformers/integration_tests/vat_heal.go @@ -23,6 +23,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_heal" @@ -32,7 +33,7 @@ import ( var _ = Describe("VatHeal Transformer", func() { It("transforms VatHeal log events", func() { blockNumber := int64(8935578) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.VatHealLabel, ContractAddresses: []string{test_data.KovanVatContractAddress}, ContractAbi: test_data.KovanVatABI, @@ -54,7 +55,7 @@ var _ = Describe("VatHeal Transformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/vat_init.go b/pkg/transformers/integration_tests/vat_init.go index 0835e396..23c9beb8 100644 --- a/pkg/transformers/integration_tests/vat_init.go +++ b/pkg/transformers/integration_tests/vat_init.go @@ -26,6 +26,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "strconv" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_init" "github.com/vulcanize/vulcanizedb/test_config" ) @@ -33,7 +34,7 @@ import ( var _ = Describe("VatInit LogNoteTransformer", func() { It("transforms VatInit log events", func() { blockNumber := int64(8535561) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.VatInitLabel, ContractAddresses: []string{test_data.KovanVatContractAddress}, ContractAbi: test_data.KovanVatABI, @@ -55,7 +56,7 @@ var _ = Describe("VatInit LogNoteTransformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/vat_move.go b/pkg/transformers/integration_tests/vat_move.go index ffa3b2ed..6a1c7517 100644 --- a/pkg/transformers/integration_tests/vat_move.go +++ b/pkg/transformers/integration_tests/vat_move.go @@ -25,6 +25,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_move" "github.com/vulcanize/vulcanizedb/test_config" ) @@ -32,7 +33,7 @@ import ( var _ = Describe("VatMove LogNoteTransformer", func() { It("transforms VatMove log events", func() { blockNumber := int64(9004628) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.VatMoveLabel, ContractAddresses: []string{test_data.KovanVatContractAddress}, ContractAbi: test_data.KovanVatABI, @@ -54,7 +55,7 @@ var _ = Describe("VatMove LogNoteTransformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/vat_slip.go b/pkg/transformers/integration_tests/vat_slip.go index f5ba2560..5b723c5c 100644 --- a/pkg/transformers/integration_tests/vat_slip.go +++ b/pkg/transformers/integration_tests/vat_slip.go @@ -8,6 +8,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "strconv" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" @@ -33,7 +34,7 @@ var _ = Describe("Vat slip transformer", func() { It("persists vat slip event", func() { blockNumber := int64(8953655) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.VatSlipLabel, ContractAddresses: []string{test_data.KovanVatContractAddress}, ContractAbi: test_data.KovanVatABI, @@ -47,7 +48,7 @@ var _ = Describe("Vat slip transformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/vat_tune.go b/pkg/transformers/integration_tests/vat_tune.go index c962f278..674d963d 100644 --- a/pkg/transformers/integration_tests/vat_tune.go +++ b/pkg/transformers/integration_tests/vat_tune.go @@ -26,6 +26,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_tune" @@ -35,7 +36,7 @@ import ( var _ = Describe("VatTune LogNoteTransformer", func() { It("transforms VatTune log events", func() { blockNumber := int64(8761670) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.VatTuneLabel, ContractAddresses: []string{test_data.KovanVatContractAddress}, ContractAbi: test_data.KovanVatABI, @@ -57,7 +58,7 @@ var _ = Describe("VatTune LogNoteTransformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/vow_flog.go b/pkg/transformers/integration_tests/vow_flog.go index 545a7680..e8aedb3f 100644 --- a/pkg/transformers/integration_tests/vow_flog.go +++ b/pkg/transformers/integration_tests/vow_flog.go @@ -25,6 +25,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/vow_flog" @@ -48,7 +49,7 @@ var _ = Describe("VowFlog LogNoteTransformer", func() { It("transforms VowFlog log events", func() { blockNumber := int64(8946819) - config := shared.TransformerConfig{ + config := shared_t.TransformerConfig{ TransformerName: constants.VowFlogLabel, ContractAddresses: []string{test_data.KovanVowContractAddress}, ContractAbi: test_data.KovanVowABI, @@ -62,7 +63,7 @@ var _ = Describe("VowFlog LogNoteTransformer", func() { fetcher := shared.NewFetcher(blockChain) logs, err := fetcher.FetchLogs( - shared.HexStringsToAddresses(config.ContractAddresses), + shared_t.HexStringsToAddresses(config.ContractAddresses), []common.Hash{common.HexToHash(config.Topic)}, header) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/pit_file/debt_ceiling/config.go b/pkg/transformers/pit_file/debt_ceiling/config.go index 70ab91fc..356432be 100644 --- a/pkg/transformers/pit_file/debt_ceiling/config.go +++ b/pkg/transformers/pit_file/debt_ceiling/config.go @@ -17,12 +17,12 @@ package debt_ceiling import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetDebtCeilingFileConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetDebtCeilingFileConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.PitFileDebtCeilingLabel, ContractAddresses: []string{constants.PitContractAddress()}, ContractAbi: constants.PitABI(), diff --git a/pkg/transformers/pit_file/ilk/config.go b/pkg/transformers/pit_file/ilk/config.go index 6ac0374e..4b29caaf 100644 --- a/pkg/transformers/pit_file/ilk/config.go +++ b/pkg/transformers/pit_file/ilk/config.go @@ -17,12 +17,12 @@ package ilk import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetIlkFileConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetIlkFileConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.PitFileIlkLabel, ContractAddresses: []string{constants.PitContractAddress()}, ContractAbi: constants.PitABI(), diff --git a/pkg/transformers/price_feeds/config.go b/pkg/transformers/price_feeds/config.go index bff9a8ec..437ba879 100644 --- a/pkg/transformers/price_feeds/config.go +++ b/pkg/transformers/price_feeds/config.go @@ -17,12 +17,13 @@ package price_feeds import ( + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetPriceFeedConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetPriceFeedConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.PriceFeedLabel, ContractAddresses: []string{ constants.PepContractAddress(), constants.PipContractAddress(), constants.RepContractAddress(), diff --git a/pkg/transformers/shared/log_chunker.go b/pkg/transformers/shared/log_chunker.go index 183bb7d3..75e1062a 100644 --- a/pkg/transformers/shared/log_chunker.go +++ b/pkg/transformers/shared/log_chunker.go @@ -20,10 +20,12 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "strings" + + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" ) type Chunker interface { - AddConfigs(transformerConfigs []TransformerConfig) + AddConfigs(transformerConfigs []shared_t.TransformerConfig) ChunkLogs(logs []types.Log) map[string][]types.Log } @@ -42,7 +44,7 @@ func NewLogChunker() *LogChunker { } // Configures the chunker by adding more addreses and topics to consider. -func (chunker *LogChunker) AddConfigs(transformerConfigs []TransformerConfig) { +func (chunker *LogChunker) AddConfigs(transformerConfigs []shared_t.TransformerConfig) { for _, config := range transformerConfigs { for _, address := range config.ContractAddresses { var lowerCaseAddress = strings.ToLower(address) diff --git a/pkg/transformers/shared/log_chunker_test.go b/pkg/transformers/shared/log_chunker_test.go index cc75d7aa..c783c40b 100644 --- a/pkg/transformers/shared/log_chunker_test.go +++ b/pkg/transformers/shared/log_chunker_test.go @@ -21,34 +21,35 @@ import ( "github.com/ethereum/go-ethereum/core/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" ) var _ = Describe("Log chunker", func() { var ( - configs []shared.TransformerConfig + configs []shared_t.TransformerConfig chunker *shared.LogChunker ) BeforeEach(func() { - configA := shared.TransformerConfig{ + configA := shared_t.TransformerConfig{ TransformerName: "TransformerA", ContractAddresses: []string{"0x00000000000000000000000000000000000000A1", "0x00000000000000000000000000000000000000A2"}, Topic: "0xA", } - configB := shared.TransformerConfig{ + configB := shared_t.TransformerConfig{ TransformerName: "TransformerB", ContractAddresses: []string{"0x00000000000000000000000000000000000000B1"}, Topic: "0xB", } - configC := shared.TransformerConfig{ + configC := shared_t.TransformerConfig{ TransformerName: "TransformerC", ContractAddresses: []string{"0x00000000000000000000000000000000000000A2"}, Topic: "0xC", } - configs = []shared.TransformerConfig{configA, configB, configC} + configs = []shared_t.TransformerConfig{configA, configB, configC} chunker = shared.NewLogChunker() chunker.AddConfigs(configs) }) @@ -71,24 +72,24 @@ var _ = Describe("Log chunker", func() { Describe("AddConfigs", func() { It("can add more configs later", func() { - configD := shared.TransformerConfig{ + configD := shared_t.TransformerConfig{ TransformerName: "TransformerD", ContractAddresses: []string{"0x000000000000000000000000000000000000000D"}, Topic: "0xD", } - chunker.AddConfigs([]shared.TransformerConfig{configD}) + chunker.AddConfigs([]shared_t.TransformerConfig{configD}) Expect(chunker.AddressToNames).To(ContainElement([]string{"TransformerD"})) Expect(chunker.NameToTopic0).To(ContainElement(common.HexToHash("0xD"))) }) It("lower cases address", func() { - configD := shared.TransformerConfig{ + configD := shared_t.TransformerConfig{ TransformerName: "TransformerD", ContractAddresses: []string{"0x000000000000000000000000000000000000000D"}, Topic: "0xD", } - chunker.AddConfigs([]shared.TransformerConfig{configD}) + chunker.AddConfigs([]shared_t.TransformerConfig{configD}) Expect(chunker.AddressToNames["0x000000000000000000000000000000000000000d"]).To(Equal([]string{"TransformerD"})) }) diff --git a/pkg/transformers/tend/config.go b/pkg/transformers/tend/config.go index 8013e97d..8fc4f0c2 100644 --- a/pkg/transformers/tend/config.go +++ b/pkg/transformers/tend/config.go @@ -17,12 +17,13 @@ package tend import ( + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetTendConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetTendConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.TendLabel, ContractAddresses: []string{constants.FlapperContractAddress(), constants.FlipperContractAddress()}, ContractAbi: constants.FlipperABI(), diff --git a/pkg/transformers/test_data/generic.go b/pkg/transformers/test_data/generic.go index db5c8a0f..d373dd6c 100644 --- a/pkg/transformers/test_data/generic.go +++ b/pkg/transformers/test_data/generic.go @@ -17,11 +17,12 @@ package test_data import ( - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "math/rand" "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" ) type GenericModel struct{} @@ -37,7 +38,7 @@ var GenericTestLogs = []types.Log{{ BlockNumber: uint64(startingBlockNumber), }} -var GenericTestConfig = shared.TransformerConfig{ +var GenericTestConfig = shared_t.TransformerConfig{ TransformerName: "generic-test-transformer", ContractAddresses: []string{address}, ContractAbi: randomString(100), diff --git a/pkg/transformers/test_data/mocks/transformer.go b/pkg/transformers/test_data/mocks/transformer.go index 452e5794..f0d5da49 100644 --- a/pkg/transformers/test_data/mocks/transformer.go +++ b/pkg/transformers/test_data/mocks/transformer.go @@ -2,9 +2,10 @@ package mocks import ( "github.com/ethereum/go-ethereum/core/types" + + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) @@ -13,7 +14,7 @@ type MockTransformer struct { ExecuteError error PassedLogs []types.Log PassedHeader core.Header - config shared.TransformerConfig + config shared_t.TransformerConfig } func (mh *MockTransformer) Execute(logs []types.Log, header core.Header, recheckHeaders constants.TransformerExecution) error { @@ -26,19 +27,19 @@ func (mh *MockTransformer) Execute(logs []types.Log, header core.Header, recheck return nil } -func (mh *MockTransformer) GetConfig() shared.TransformerConfig { +func (mh *MockTransformer) GetConfig() shared_t.TransformerConfig { return mh.config } -func (mh *MockTransformer) SetTransformerConfig(config shared.TransformerConfig) { +func (mh *MockTransformer) SetTransformerConfig(config shared_t.TransformerConfig) { mh.config = config } -func (mh *MockTransformer) FakeTransformerInitializer(db *postgres.DB) shared.Transformer { +func (mh *MockTransformer) FakeTransformerInitializer(db *postgres.DB) shared_t.Transformer { return mh } -var FakeTransformerConfig = shared.TransformerConfig{ +var FakeTransformerConfig = shared_t.TransformerConfig{ TransformerName: "FakeTransformer", ContractAddresses: []string{"FakeAddress"}, Topic: "FakeTopic", diff --git a/pkg/transformers/transformers.go b/pkg/transformers/transformers.go index 3e5625fb..04acc76e 100644 --- a/pkg/transformers/transformers.go +++ b/pkg/transformers/transformers.go @@ -17,6 +17,7 @@ package transformers import ( + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/bite" "github.com/vulcanize/vulcanizedb/pkg/transformers/cat_file/chop_lump" "github.com/vulcanize/vulcanizedb/pkg/transformers/cat_file/flip" @@ -35,7 +36,6 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/debt_ceiling" "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/ilk" "github.com/vulcanize/vulcanizedb/pkg/transformers/price_feeds" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/tend" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_flux" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_fold" @@ -315,7 +315,7 @@ func getLogNoteTransformers() []factories.LogNoteTransformer { // `TransformerInitializers` returns a list of functions, that given a db pointer // will return a `shared.Transformer` -func TransformerInitializers() (initializers []shared.TransformerInitializer) { +func TransformerInitializers() (initializers []shared_t.TransformerInitializer) { for _, transformer := range getLogNoteTransformers() { initializers = append(initializers, transformer.NewLogNoteTransformer) } diff --git a/pkg/transformers/vat_flux/config.go b/pkg/transformers/vat_flux/config.go index e33d8d34..f4b347eb 100644 --- a/pkg/transformers/vat_flux/config.go +++ b/pkg/transformers/vat_flux/config.go @@ -1,12 +1,12 @@ package vat_flux import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetVatFluxConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetVatFluxConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.VatFluxLabel, ContractAddresses: []string{constants.VatContractAddress()}, ContractAbi: constants.VatABI(), diff --git a/pkg/transformers/vat_fold/config.go b/pkg/transformers/vat_fold/config.go index f8e35c17..27fd3427 100644 --- a/pkg/transformers/vat_fold/config.go +++ b/pkg/transformers/vat_fold/config.go @@ -17,12 +17,12 @@ package vat_fold import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetVatFoldConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetVatFoldConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.VatFoldLabel, ContractAddresses: []string{constants.VatContractAddress()}, ContractAbi: constants.VatABI(), diff --git a/pkg/transformers/vat_grab/config.go b/pkg/transformers/vat_grab/config.go index 89b8b309..ce653677 100644 --- a/pkg/transformers/vat_grab/config.go +++ b/pkg/transformers/vat_grab/config.go @@ -1,12 +1,12 @@ package vat_grab import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetVatGrabConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetVatGrabConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.VatGrabLabel, ContractAddresses: []string{constants.VatContractAddress()}, ContractAbi: constants.VatABI(), diff --git a/pkg/transformers/vat_heal/config.go b/pkg/transformers/vat_heal/config.go index 4bc0831c..2e4ec56f 100644 --- a/pkg/transformers/vat_heal/config.go +++ b/pkg/transformers/vat_heal/config.go @@ -17,12 +17,12 @@ package vat_heal import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetVatHealConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetVatHealConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.VatHealLabel, ContractAddresses: []string{constants.VatContractAddress()}, ContractAbi: constants.VatABI(), diff --git a/pkg/transformers/vat_init/config.go b/pkg/transformers/vat_init/config.go index 7d83c9d5..95a4a2f9 100644 --- a/pkg/transformers/vat_init/config.go +++ b/pkg/transformers/vat_init/config.go @@ -17,12 +17,12 @@ package vat_init import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetVatInitConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetVatInitConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.VatInitLabel, ContractAddresses: []string{constants.VatContractAddress()}, ContractAbi: constants.VatABI(), diff --git a/pkg/transformers/vat_move/config.go b/pkg/transformers/vat_move/config.go index 6f8884d3..03c990bd 100644 --- a/pkg/transformers/vat_move/config.go +++ b/pkg/transformers/vat_move/config.go @@ -17,12 +17,12 @@ package vat_move import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetVatMoveConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetVatMoveConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.VatMoveLabel, ContractAddresses: []string{constants.VatContractAddress()}, ContractAbi: constants.VatABI(), diff --git a/pkg/transformers/vat_slip/config.go b/pkg/transformers/vat_slip/config.go index db910f51..d095b8c1 100644 --- a/pkg/transformers/vat_slip/config.go +++ b/pkg/transformers/vat_slip/config.go @@ -1,12 +1,12 @@ package vat_slip import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetVatSlipConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetVatSlipConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.VatSlipLabel, ContractAddresses: []string{constants.VatContractAddress()}, ContractAbi: constants.VatABI(), diff --git a/pkg/transformers/vat_toll/config.go b/pkg/transformers/vat_toll/config.go index 0003dc2b..998026d4 100644 --- a/pkg/transformers/vat_toll/config.go +++ b/pkg/transformers/vat_toll/config.go @@ -1,12 +1,12 @@ package vat_toll import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetVatTollConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetVatTollConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.VatTollLabel, ContractAddresses: []string{constants.VatContractAddress()}, ContractAbi: constants.VatABI(), diff --git a/pkg/transformers/vat_tune/config.go b/pkg/transformers/vat_tune/config.go index 1a323258..cd3627a6 100644 --- a/pkg/transformers/vat_tune/config.go +++ b/pkg/transformers/vat_tune/config.go @@ -1,12 +1,12 @@ package vat_tune import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetVatTuneConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetVatTuneConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.VatTuneLabel, ContractAddresses: []string{constants.VatContractAddress()}, ContractAbi: constants.VatABI(), diff --git a/pkg/transformers/vow_flog/config.go b/pkg/transformers/vow_flog/config.go index ca32ced2..5f46ec82 100644 --- a/pkg/transformers/vow_flog/config.go +++ b/pkg/transformers/vow_flog/config.go @@ -17,12 +17,12 @@ package vow_flog import ( - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + shared_t "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared/constants" ) -func GetVowFlogConfig() shared.TransformerConfig { - return shared.TransformerConfig{ +func GetVowFlogConfig() shared_t.TransformerConfig { + return shared_t.TransformerConfig{ TransformerName: constants.VowFlogLabel, ContractAddresses: []string{constants.VowContractAddress()}, ContractAbi: constants.VowABI(), diff --git a/plugins/README.md b/plugins/README.md new file mode 100644 index 00000000..390eaeca --- /dev/null +++ b/plugins/README.md @@ -0,0 +1,58 @@ +## Plugins + +This directory is for Exporter plugins (.go and .so files) generated by, output from, and linked to from the composeAndExecute command +These plugins are generated using information provided in a .toml config file + +The config file requires, at a minimum, the below fields: + +```toml +[database] + name = "vulcanize_public" + hostname = "localhost" + user = "vulcanize" + password = "vulcanize" + port = 5432 + +[client] + ipcPath = "http://kovan0.vulcanize.io:8545" + +[exporter] + filePath = "$GOPATH/src/github.com/vulcanize/vulcanizedb/plugins/" + fileName = "exporter" + [exporter.transformers] + transformer1 = "github.com/path/to/transformer1" + transformer2 = "github.com/path/to/transformer2" + transformer3 = "github.com/path/to/transformer3" +``` + +In the above, the exporter.transformers are mappings of import aliases to their import paths +If the individual transformers require additional configuration variables be sure to include them in the .toml file + +The general structure of a plugin .go file, and what we would see with the above config is below +Note that `shared_transformer` is a reserved alias needed for the generic TransformerInitializer type: + +```go +package main + +import ( + shared_transformer "github.com/vulcanize/vulcanizedb/libraries/shared/transformer" + transformer1 "github.com/path/to/transformer1" + transformer2 "github.com/path/to/transformer2" + transformer3 "github.com/path/to/transformer3" +) + +type exporter string + +var Exporter exporter + +func (e exporter) Export() []shared_transformer.TransformerInitializer { + return []shared_transformer.TransformerInitializer{ + transformer1.TransformerInitializer, + transformer2.TransformerInitializer, + transformer3.TransformerInitializer, + } +} +``` + +As such, to plug in an external transformer all we need to do is create a [package](https://github.com/vulcanize/maker-vulcanizedb/blob/compose_and_execute/pkg/autogen/test_helpers/bite/initializer.go) that exports a variable `TransformerInitializer` that is of type [TransformerInitializer](https://github.com/vulcanize/maker-vulcanizedb/blob/compose_and_execute/libraries/shared/transformer/transformer.go#L19) +As long as the imported transformers abide by the required interfaces, we can execute over any arbitrary set of them \ No newline at end of file diff --git a/vendor/github.com/dave/jennifer/.gitignore b/vendor/github.com/dave/jennifer/.gitignore new file mode 100644 index 00000000..f5730045 --- /dev/null +++ b/vendor/github.com/dave/jennifer/.gitignore @@ -0,0 +1,30 @@ +*.iml + +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +.DS_Store +.idea/ +coverage.out diff --git a/vendor/github.com/dave/jennifer/.travis.yml b/vendor/github.com/dave/jennifer/.travis.yml new file mode 100644 index 00000000..1b62d095 --- /dev/null +++ b/vendor/github.com/dave/jennifer/.travis.yml @@ -0,0 +1,14 @@ +language: go +go: + - 1.x +notificaitons: + email: + recipients: dave@brophy.uk + on_failure: always +install: + - go get -u github.com/dave/courtney + - go get -t -v ./... +script: + - courtney -e +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/dave/jennifer/LICENSE b/vendor/github.com/dave/jennifer/LICENSE new file mode 100644 index 00000000..17ab1ced --- /dev/null +++ b/vendor/github.com/dave/jennifer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 David Brophy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/dave/jennifer/README.md b/vendor/github.com/dave/jennifer/README.md new file mode 100644 index 00000000..2d9060cd --- /dev/null +++ b/vendor/github.com/dave/jennifer/README.md @@ -0,0 +1,1052 @@ +[![Build Status](https://travis-ci.org/dave/jennifer.svg?branch=master)](https://travis-ci.org/dave/jennifer) [![Go Report Card](https://goreportcard.com/badge/github.com/dave/jennifer)](https://goreportcard.com/report/github.com/dave/jennifer) [![codecov](https://img.shields.io/badge/codecov-100%25-brightgreen.svg)](https://codecov.io/gh/dave/jennifer) ![stability-stable](https://img.shields.io/badge/stability-stable-brightgreen.svg) [![Sourcegraph](https://sourcegraph.com/github.com/dave/jennifer/jen/-/badge.svg)](https://sourcegraph.com/github.com/dave/jennifer?badge) + +# Jennifer +Jennifer is a code generator for Go. + +```go +package main + +import ( + "fmt" + + . "github.com/dave/jennifer/jen" +) + +func main() { + f := NewFile("main") + f.Func().Id("main").Params().Block( + Qual("fmt", "Println").Call(Lit("Hello, world")), + ) + fmt.Printf("%#v", f) +} +``` +Output: +```go +package main + +import "fmt" + +func main() { + fmt.Println("Hello, world") +} +``` + +### Install +``` +go get -u github.com/dave/jennifer/jen +``` + +### Need help? +If you get stuck, have a question, would like a code review, or just want a +chat: I'm happy to help! Feel free to open an issue, email me or mention @dave +in your PR. + +### Examples +Jennifer has a comprehensive suite of examples - see [godoc](https://godoc.org/github.com/dave/jennifer/jen#pkg-examples) for an index. Here's some examples of jennifer being used in the real-world: + +* [genjen](genjen/render.go) (which generates much of jennifer, using data in [data.go](genjen/data.go)) +* [zerogen](https://github.com/mrsinham/zerogen/blob/master/generator.go) +* [go-contentful-generator](https://github.com/nicolai86/go-contentful-generator) + +### Rendering +For testing, a File or Statement can be rendered with the fmt package +using the %#v verb. + +```go +c := Id("a").Call(Lit("b")) +fmt.Printf("%#v", c) +// Output: +// a("b") +``` + +This is not recommended for use in production because any error will cause a +panic. For production use, [File.Render](#render) or [File.Save](#save) are +preferred. + +# Identifiers +**Identifiers** [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +### Id +Id renders an identifier. + +```go +c := If(Id("i").Op("==").Id("j")).Block( + Return(Id("i")), +) +fmt.Printf("%#v", c) +// Output: +// if i == j { +// return i +// } +``` + +### Dot +Dot renders a period followed by an identifier. Use for fields and selectors. + +```go +c := Qual("a.b/c", "Foo").Call().Dot("Bar").Index(Lit(0)).Dot("Baz") +fmt.Printf("%#v", c) +// Output: +// c.Foo().Bar[0].Baz +``` + +### Qual +Qual renders a qualified identifier. + +```go +c := Qual("encoding/gob", "NewEncoder").Call() +fmt.Printf("%#v", c) +// Output: +// gob.NewEncoder() +``` + +Imports are automatically added when +used with a File. If the path matches the local path, the package name is +omitted. If package names conflict they are automatically renamed. + +```go +f := NewFilePath("a.b/c") +f.Func().Id("init").Params().Block( + Qual("a.b/c", "Foo").Call().Comment("Local package - name is omitted."), + Qual("d.e/f", "Bar").Call().Comment("Import is automatically added."), + Qual("g.h/f", "Baz").Call().Comment("Colliding package name is renamed."), +) +fmt.Printf("%#v", f) +// Output: +// package c +// +// import ( +// f "d.e/f" +// f1 "g.h/f" +// ) +// +// func init() { +// Foo() // Local package - name is omitted. +// f.Bar() // Import is automatically added. +// f1.Baz() // Colliding package name is renamed. +// } +``` + +Note that +it is not possible to reliably determine the package name given an arbitrary +package path, so a sensible name is guessed from the path and added as an +alias. The names of all standard library packages are known so these do not +need to be aliased. If more control is needed of the aliases, see +[File.ImportName](#importname) or [File.ImportAlias](#importalias). + +### List +List renders a comma separated list. Use for multiple return functions. + +```go +c := List(Id("a"), Err()).Op(":=").Id("b").Call() +fmt.Printf("%#v", c) +// Output: +// a, err := b() +``` + +# Keywords +[Identifiers](#identifiers) **Keywords** [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +Simple keywords, predeclared identifiers and built-in functions are self +explanatory: + +| Construct | Name | +| ---------------- | ---- | +| Keywords | Break, Chan, Const, Continue, Default, Defer, Else, Fallthrough, Func, Go, Goto, Range, Select, Type, Var | +| Functions | Append, Cap, Close, Complex, Copy, Delete, Imag, Len, Make, New, Panic, Print, Println, Real, Recover | +| Types | Bool, Byte, Complex64, Complex128, Error, Float32, Float64, Int, Int8, Int16, Int32, Int64, Rune, String, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr | +| Constants | True, False, Iota, Nil | +| Helpers | Err | + +Built-in functions take a list of parameters and render them appropriately: + +```go +c := Id("a").Op("=").Append(Id("a"), Id("b").Op("...")) +fmt.Printf("%#v", c) +// Output: +// a = append(a, b...) +``` + +Special cases for [If, For](#if-for), [Interface, Struct](#interface-struct), [Switch, Case](#switch-select), [Return](#return) and [Map](#map) are explained below. + +# Operators +[Identifiers](#identifiers) [Keywords](#keywords) **Operators** [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +Op renders the provided operator / token. + +```go +c := Id("a").Op(":=").Id("b").Call() +fmt.Printf("%#v", c) +// Output: +// a := b() +``` + +```go +c := Id("a").Op("=").Op("*").Id("b") +fmt.Printf("%#v", c) +// Output: +// a = *b +``` + +```go +c := Id("a").Call(Id("b").Op("...")) +fmt.Printf("%#v", c) +// Output: +// a(b...) +``` + +```go +c := If(Parens(Id("a").Op("||").Id("b")).Op("&&").Id("c")).Block() +fmt.Printf("%#v", c) +// Output: +// if (a || b) && c { +// } +``` + +# Braces +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) **Braces** [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +Several methods render curly braces, summarized below: + +| Name | Prefix | Separator | Example | +| ------------------------------ | ------------ | --------- | -------------------------------------| +| [Block](#block) | | `\n` | `func a() { ... }` or `if a { ... }` | +| [Interface](#interface-struct) | `interface` | `\n` | `interface { ... }` | +| [Struct](#interface-struct) | `struct` | `\n` | `struct { ... }` | +| [Values](#values) | | `,` | `[]int{1, 2}` or `A{B: "c"}` | + +### Block +Block renders a statement list enclosed by curly braces. Use for code blocks. + +```go +c := Func().Id("foo").Params().String().Block( + Id("a").Op("=").Id("b"), + Id("b").Op("++"), + Return(Id("b")), +) +fmt.Printf("%#v", c) +// Output: +// func foo() string { +// a = b +// b++ +// return b +// } +``` + +```go +c := If(Id("a").Op(">").Lit(10)).Block( + Id("a").Op("=").Id("a").Op("/").Lit(2), +) +fmt.Printf("%#v", c) +// Output: +// if a > 10 { +// a = a / 2 +// } +``` + +A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. [See example](#switch-select). + +### Interface, Struct +Interface and Struct render the keyword followed by a statement list enclosed +by curly braces. + +```go +c := Var().Id("a").Interface() +fmt.Printf("%#v", c) +// Output: +// var a interface{} +``` + +```go +c := Type().Id("a").Interface( + Id("b").Params().String(), +) +fmt.Printf("%#v", c) +// Output: +// type a interface { +// b() string +// } +``` + +```go +c := Id("c").Op(":=").Make(Chan().Struct()) +fmt.Printf("%#v", c) +// Output: +// c := make(chan struct{}) +``` + +```go +c := Type().Id("foo").Struct( + List(Id("x"), Id("y")).Int(), + Id("u").Float32(), +) +fmt.Printf("%#v", c) +// Output: +// type foo struct { +// x, y int +// u float32 +// } +``` + +# Parentheses +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) **Parentheses** [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +Several methods output parenthesis, summarized below: + +| Name | Prefix | Separator | Example | +| ----------------- | ------ | --------- | --------------------------------- | +| [Call](#call) | | `,` | `fmt.Println(b, c)` | +| [Params](#params) | | `,` | `func (a *A) Foo(i int) { ... }` | +| [Defs](#defs) | | `\n` | `const ( ... )` | +| [Parens](#parens) | | | `[]byte(s)` or `a / (b + c)` | +| [Assert](#assert) | `.` | | `s, ok := i.(string)` | + +### Call +Call renders a comma separated list enclosed by parenthesis. Use for function calls. + +```go +c := Qual("fmt", "Printf").Call( + Lit("%#v: %T\n"), + Id("a"), + Id("b"), +) +fmt.Printf("%#v", c) +// Output: +// fmt.Printf("%#v: %T\n", a, b) +``` + +### Params +Params renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. + +```go +c := Func().Params( + Id("a").Id("A"), +).Id("foo").Params( + Id("b"), + Id("c").String(), +).String().Block( + Return(Id("b").Op("+").Id("c")), +) +fmt.Printf("%#v", c) +// Output: +// func (a A) foo(b, c string) string { +// return b + c +// } +``` + +### Defs +Defs renders a statement list enclosed in parenthesis. Use for definition lists. + +```go +c := Const().Defs( + Id("a").Op("=").Lit("a"), + Id("b").Op("=").Lit("b"), +) +fmt.Printf("%#v", c) +// Output: +// const ( +// a = "a" +// b = "b" +// ) +``` + +### Parens +Parens renders a single item in parenthesis. Use for type conversion or to specify evaluation order. + +```go +c := Id("b").Op(":=").Index().Byte().Parens(Id("s")) +fmt.Printf("%#v", c) +// Output: +// b := []byte(s) +``` + +```go +c := Id("a").Op("/").Parens(Id("b").Op("+").Id("c")) +fmt.Printf("%#v", c) +// Output: +// a / (b + c) +``` + +### Assert +Assert renders a period followed by a single item enclosed by parenthesis. Use for type assertions. + +```go +c := List(Id("b"), Id("ok")).Op(":=").Id("a").Assert(Bool()) +fmt.Printf("%#v", c) +// Output: +// b, ok := a.(bool) +``` + +# Control flow +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) **Control flow** [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +### If, For +If and For render the keyword followed by a semicolon separated list. + +```go +c := If( + Err().Op(":=").Id("a").Call(), + Err().Op("!=").Nil(), +).Block( + Return(Err()), +) +fmt.Printf("%#v", c) +// Output: +// if err := a(); err != nil { +// return err +// } +``` + +```go +c := For( + Id("i").Op(":=").Lit(0), + Id("i").Op("<").Lit(10), + Id("i").Op("++"), +).Block( + Qual("fmt", "Println").Call(Id("i")), +) +fmt.Printf("%#v", c) +// Output: +// for i := 0; i < 10; i++ { +// fmt.Println(i) +// } +``` + +### Switch, Select +Switch, Select, Case and Block are used to build switch or select statements: + +```go +c := Switch(Id("value").Dot("Kind").Call()).Block( + Case(Qual("reflect", "Float32"), Qual("reflect", "Float64")).Block( + Return(Lit("float")), + ), + Case(Qual("reflect", "Bool")).Block( + Return(Lit("bool")), + ), + Case(Qual("reflect", "Uintptr")).Block( + Fallthrough(), + ), + Default().Block( + Return(Lit("none")), + ), +) +fmt.Printf("%#v", c) +// Output: +// switch value.Kind() { +// case reflect.Float32, reflect.Float64: +// return "float" +// case reflect.Bool: +// return "bool" +// case reflect.Uintptr: +// fallthrough +// default: +// return "none" +// } +``` + +### Return +Return renders the keyword followed by a comma separated list. + +```go +c := Return(Id("a"), Id("b")) +fmt.Printf("%#v", c) +// Output: +// return a, b +``` + +# Collections +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) **Collections** [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +### Map +Map renders the keyword followed by a single item enclosed by square brackets. Use for map definitions. + +```go +c := Id("a").Op(":=").Map(String()).String().Values() +fmt.Printf("%#v", c) +// Output: +// a := map[string]string{} +``` + +### Index +Index renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. + +```go +c := Var().Id("a").Index().String() +fmt.Printf("%#v", c) +// Output: +// var a []string +``` + +```go +c := Id("a").Op(":=").Id("b").Index(Lit(0), Lit(1)) +fmt.Printf("%#v", c) +// Output: +// a := b[0:1] +``` + +```go +c := Id("a").Op(":=").Id("b").Index(Lit(1), Empty()) +fmt.Printf("%#v", c) +// Output: +// a := b[1:] +``` + +### Values +Values renders a comma separated list enclosed by curly braces. Use for slice or composite literals. + +```go +c := Index().String().Values(Lit("a"), Lit("b")) +fmt.Printf("%#v", c) +// Output: +// []string{"a", "b"} +``` + +Dict renders as key/value pairs. Use with Values for map or composite +literals. + +```go +c := Map(String()).String().Values(Dict{ + Lit("a"): Lit("b"), + Lit("c"): Lit("d"), +}) +fmt.Printf("%#v", c) +// Output: +// map[string]string{ +// "a": "b", +// "c": "d", +// } +``` + +```go +c := Op("&").Id("Person").Values(Dict{ + Id("Age"): Lit(1), + Id("Name"): Lit("a"), +}) +fmt.Printf("%#v", c) +// Output: +// &Person{ +// Age: 1, +// Name: "a", +// } +``` + +DictFunc executes a func(Dict) to generate the value. + +```go +c := Id("a").Op(":=").Map(String()).String().Values(DictFunc(func(d Dict) { + d[Lit("a")] = Lit("b") + d[Lit("c")] = Lit("d") +})) +fmt.Printf("%#v", c) +// Output: +// a := map[string]string{ +// "a": "b", +// "c": "d", +// } +``` + +Note: the items are ordered by key when rendered to ensure repeatable code. + +# Literals +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) **Literals** [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +### Lit +Lit renders a literal. Lit supports only built-in types (bool, string, int, complex128, float64, +float32, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr and complex64). +Passing any other type will panic. + +```go +c := Id("a").Op(":=").Lit("a") +fmt.Printf("%#v", c) +// Output: +// a := "a" +``` + +```go +c := Id("a").Op(":=").Lit(1.5) +fmt.Printf("%#v", c) +// Output: +// a := 1.5 +``` + +LitFunc generates the value to render by executing the provided +function. + +```go +c := Id("a").Op(":=").LitFunc(func() interface{} { return 1 + 1 }) +fmt.Printf("%#v", c) +// Output: +// a := 2 +``` + +For the default constant types (bool, int, float64, string, complex128), Lit +will render the untyped constant. + +| Code | Output | +| ------------- | ---------- | +| `Lit(true)` | `true` | +| `Lit(1)` | `1` | +| `Lit(1.0)` | `1.0` | +| `Lit("foo")` | `"foo"` | +| `Lit(0 + 1i)` | `(0 + 1i)` | + +For all other built-in types (float32, int8, int16, int32, int64, uint, uint8, +uint16, uint32, uint64, uintptr, complex64), Lit will also render the type. + +| Code | Output | +| ------------------------ | ------------------- | +| `Lit(float32(1))` | `float32(1)` | +| `Lit(int16(1))` | `int16(1)` | +| `Lit(uint8(0x1))` | `uint8(0x1)` | +| `Lit(complex64(0 + 1i))` | `complex64(0 + 1i)` | + +The built-in alias types byte and rune need a special case. LitRune and LitByte +render rune and byte literals. + +| Code | Output | +| ------------------------ | ----------- | +| `LitRune('x')` | `'x'` | +| `LitByte(byte(0x1))` | `byte(0x1)` | + +# Comments +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) **Comments** [Helpers](#helpers) [Misc](#misc) [File](#file) + +### Comment +Comment adds a comment. If the provided string contains a newline, the +comment is formatted in multiline style. + +```go +f := NewFile("a") +f.Comment("Foo returns the string \"foo\"") +f.Func().Id("Foo").Params().String().Block( + Return(Lit("foo")).Comment("return the string foo"), +) +fmt.Printf("%#v", f) +// Output: +// package a +// +// // Foo returns the string "foo" +// func Foo() string { +// return "foo" // return the string foo +// } +``` + +```go +c := Comment("a\nb") +fmt.Printf("%#v", c) +// Output: +// /* +// a +// b +// */ +``` + +If the comment string starts +with "//" or "/*", the automatic formatting is disabled and the string is +rendered directly. + +```go +c := Id("foo").Call(Comment("/* inline */")).Comment("//no-space") +fmt.Printf("%#v", c) +// Output: +// foo( /* inline */ ) //no-space +``` + +### Commentf +Commentf adds a comment, using a format string and a list of parameters. + +```go +name := "foo" +val := "bar" +c := Id(name).Op(":=").Lit(val).Commentf("%s is the string \"%s\"", name, val) +fmt.Printf("%#v", c) +// Output: +// foo := "bar" // foo is the string "bar" +``` + +# Helpers +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) **Helpers** [Misc](#misc) [File](#file) + +### Func methods +All constructs that accept a variadic list of items are paired with GroupFunc +functions that accept a func(*Group). Use for embedding logic. + +```go +c := Id("numbers").Op(":=").Index().Int().ValuesFunc(func(g *Group) { + for i := 0; i <= 5; i++ { + g.Lit(i) + } +}) +fmt.Printf("%#v", c) +// Output: +// numbers := []int{0, 1, 2, 3, 4, 5} +``` + +```go +increment := true +name := "a" +c := Func().Id("a").Params().BlockFunc(func(g *Group) { + g.Id(name).Op("=").Lit(1) + if increment { + g.Id(name).Op("++") + } else { + g.Id(name).Op("--") + } +}) +fmt.Printf("%#v", c) +// Output: +// func a() { +// a = 1 +// a++ +// } +``` + +### Add +Add appends the provided items to the statement. + +```go +ptr := Op("*") +c := Id("a").Op("=").Add(ptr).Id("b") +fmt.Printf("%#v", c) +// Output: +// a = *b +``` + +```go +a := Id("a") +i := Int() +c := Var().Add(a, i) +fmt.Printf("%#v", c) +// Output: +// var a int +``` + +### Do +Do calls the provided function with the statement as a parameter. Use for +embedding logic. + +```go +f := func(name string, isMap bool) *Statement { + return Id(name).Op(":=").Do(func(s *Statement) { + if isMap { + s.Map(String()).String() + } else { + s.Index().String() + } + }).Values() +} +fmt.Printf("%#v\n%#v", f("a", true), f("b", false)) +// Output: +// a := map[string]string{} +// b := []string{} +``` + +# Misc +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) **Misc** [File](#file) + +### Tag +Tag renders a struct tag + +```go +c := Type().Id("foo").Struct( + Id("A").String().Tag(map[string]string{"json": "a"}), + Id("B").Int().Tag(map[string]string{"json": "b", "bar": "baz"}), +) +fmt.Printf("%#v", c) +// Output: +// type foo struct { +// A string `json:"a"` +// B int `bar:"baz" json:"b"` +// } +``` + +Note: the items are ordered by key when rendered to ensure repeatable code. + +### Null +Null adds a null item. Null items render nothing and are not followed by a +separator in lists. + +In lists, nil will produce the same effect. + +```go +c := Func().Id("foo").Params( + nil, + Id("s").String(), + Null(), + Id("i").Int(), +).Block() +fmt.Printf("%#v", c) +// Output: +// func foo(s string, i int) {} +``` + +### Empty +Empty adds an empty item. Empty items render nothing but are followed by a +separator in lists. + +```go +c := Id("a").Op(":=").Id("b").Index(Lit(1), Empty()) +fmt.Printf("%#v", c) +// Output: +// a := b[1:] +``` + +### Line +Line inserts a blank line. + +### Clone +Be careful when passing *Statement. Consider the following... + +```go +a := Id("a") +c := Block( + a.Call(), + a.Call(), +) +fmt.Printf("%#v", c) +// Output: +// { +// a()() +// a()() +// } +``` + +Id("a") returns a *Statement, which the Call() method appends to twice. To +avoid this, use Clone. Clone makes a copy of the Statement, so further tokens can be appended +without affecting the original. + +```go +a := Id("a") +c := Block( + a.Clone().Call(), + a.Clone().Call(), +) +fmt.Printf("%#v", c) +// Output: +// { +// a() +// a() +// } +``` + +### Cgo +The cgo "C" pseudo-package is a special case, and always renders without a package alias. The +import can be added with `Qual`, `Anon` or by supplying a preamble. The preamble is added with +`File.CgoPreamble` which has the same semantics as [Comment](#comments). If a preamble is provided, +the import is separated, and preceded by the preamble. + +```go +f := NewFile("a") +f.CgoPreamble(`#include +#include + +void myprint(char* s) { +printf("%s\n", s); +} +`) +f.Func().Id("init").Params().Block( + Id("cs").Op(":=").Qual("C", "CString").Call(Lit("Hello from stdio\n")), + Qual("C", "myprint").Call(Id("cs")), + Qual("C", "free").Call(Qual("unsafe", "Pointer").Parens(Id("cs"))), +) +fmt.Printf("%#v", f) +// Output: +// package a +// +// import "unsafe" +// +// /* +// #include +// #include +// +// void myprint(char* s) { +// printf("%s\n", s); +// } +// */ +// import "C" +// +// func init() { +// cs := C.CString("Hello from stdio\n") +// C.myprint(cs) +// C.free(unsafe.Pointer(cs)) +// } +``` + +# File +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) **File** + +File represents a single source file. Package imports are managed +automaticaly by File. + +### NewFile +NewFile Creates a new file, with the specified package name. + +### NewFilePath +NewFilePath creates a new file while specifying the package path - the +package name is inferred from the path. + +### NewFilePathName +NewFilePathName creates a new file with the specified package path and name. + +```go +f := NewFilePathName("a.b/c", "main") +f.Func().Id("main").Params().Block( + Qual("a.b/c", "Foo").Call(), +) +fmt.Printf("%#v", f) +// Output: +// package main +// +// func main() { +// Foo() +// } +``` + +### Save +Save renders the file and saves to the filename provided. + +### Render +Render renders the file to the provided writer. + +```go +f := NewFile("a") +f.Func().Id("main").Params().Block() +buf := &bytes.Buffer{} +err := f.Render(buf) +if err != nil { + fmt.Println(err.Error()) +} else { + fmt.Println(buf.String()) +} +// Output: +// package a +// +// func main() {} +``` + +### Anon +Anon adds an anonymous import. + +```go +f := NewFile("c") +f.Anon("a") +f.Func().Id("init").Params().Block() +fmt.Printf("%#v", f) +// Output: +// package c +// +// import _ "a" +// +// func init() {} +``` + +### ImportName +ImportName provides the package name for a path. If specified, the alias will be omitted from the +import block. This is optional. If not specified, a sensible package name is used based on the path +and this is added as an alias in the import block. + +```go +f := NewFile("main") + +// package a should use name "a" +f.ImportName("github.com/foo/a", "a") + +// package b is not used in the code so will not be included +f.ImportName("github.com/foo/b", "b") + +f.Func().Id("main").Params().Block( + Qual("github.com/foo/a", "A").Call(), +) +fmt.Printf("%#v", f) + +// Output: +// package main +// +// import "github.com/foo/a" +// +// func main() { +// a.A() +// } +``` + +### ImportNames +ImportNames allows multiple names to be imported as a map. Use the [gennames](gennames) command to +automatically generate a go file containing a map of a selection of package names. + +### ImportAlias +ImportAlias provides the alias for a package path that should be used in the import block. A +period can be used to force a dot-import. + +```go +f := NewFile("main") + +// package a should be aliased to "b" +f.ImportAlias("github.com/foo/a", "b") + +// package c is not used in the code so will not be included +f.ImportAlias("github.com/foo/c", "c") + +f.Func().Id("main").Params().Block( + Qual("github.com/foo/a", "A").Call(), +) +fmt.Printf("%#v", f) + +// Output: +// package main +// +// import b "github.com/foo/a" +// +// func main() { +// b.A() +// } +``` + +### Comments +PackageComment adds a comment to the top of the file, above the package +keyword. + +HeaderComment adds a comment to the top of the file, above any package +comments. A blank line is rendered below the header comments, ensuring +header comments are not included in the package doc. + +CanonicalPath adds a canonical import path annotation to the package clause. + +```go +f := NewFile("c") +f.CanonicalPath = "d.e/f" +f.HeaderComment("Code generated by...") +f.PackageComment("Package c implements...") +f.Func().Id("init").Params().Block() +fmt.Printf("%#v", f) +// Output: +// // Code generated by... +// +// // Package c implements... +// package c // import "d.e/f" +// +// func init() {} +``` + +CgoPreamble adds a cgo preamble comment that is rendered directly before the "C" pseudo-package +import. + +### PackagePrefix +If you're worried about generated package aliases conflicting with local variable names, you +can set a prefix here. Package foo becomes {prefix}_foo. + +```go +f := NewFile("a") +f.PackagePrefix = "pkg" +f.Func().Id("main").Params().Block( + Qual("b.c/d", "E").Call(), +) +fmt.Printf("%#v", f) +// Output: +// package a +// +// import pkg_d "b.c/d" +// +// func main() { +// pkg_d.E() +// } +``` diff --git a/vendor/github.com/dave/jennifer/README.md.tpl b/vendor/github.com/dave/jennifer/README.md.tpl new file mode 100644 index 00000000..9000ca1d --- /dev/null +++ b/vendor/github.com/dave/jennifer/README.md.tpl @@ -0,0 +1,422 @@ +[![Build Status](https://travis-ci.org/dave/jennifer.svg?branch=master)](https://travis-ci.org/dave/jennifer) [![Go Report Card](https://goreportcard.com/badge/github.com/dave/jennifer)](https://goreportcard.com/report/github.com/dave/jennifer) [![codecov](https://img.shields.io/badge/codecov-100%25-brightgreen.svg)](https://codecov.io/gh/dave/jennifer) ![stability-stable](https://img.shields.io/badge/stability-stable-brightgreen.svg) [![Sourcegraph](https://sourcegraph.com/github.com/dave/jennifer/jen/-/badge.svg)](https://sourcegraph.com/github.com/dave/jennifer?badge) + +# Jennifer +Jennifer is a code generator for Go. + +```go +package main + +import ( + "fmt" + + . "github.com/dave/jennifer/jen" +) + +func main() {{ "ExampleNewFile" | code }} +``` +Output: +```go +{{ "ExampleNewFile" | output }} +``` + +### Install +``` +go get -u github.com/dave/jennifer/jen +``` + +### Need help? +If you get stuck, have a question, would like a code review, or just want a +chat: I'm happy to help! Feel free to open an issue, email me or mention @dave +in your PR. + +### Examples +Jennifer has a comprehensive suite of examples - see [godoc](https://godoc.org/github.com/dave/jennifer/jen#pkg-examples) for an index. Here's some examples of jennifer being used in the real-world: + +* [genjen](genjen/render.go) (which generates much of jennifer, using data in [data.go](genjen/data.go)) +* [zerogen](https://github.com/mrsinham/zerogen/blob/master/generator.go) +* [go-contentful-generator](https://github.com/nicolai86/go-contentful-generator) + +### Rendering +For testing, a File or Statement can be rendered with the fmt package +using the %#v verb. + +{{ "ExampleCall_fmt" | example }} + +This is not recommended for use in production because any error will cause a +panic. For production use, [File.Render](#render) or [File.Save](#save) are +preferred. + +# Identifiers +**Identifiers** [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +### Id +{{ "Id" | doc }} + +{{ "ExampleId" | example }} + +### Dot +{{ "Dot" | doc }} + +{{ "ExampleDot" | example }} + +### Qual +{{ "Qual[0]" | doc }} + +{{ "ExampleQual" | example }} + +{{ "Qual[1:4]" | doc }} + +{{ "ExampleQual_file" | example }} + +{{ "Qual[4:]" | doc }} + +### List +{{ "List" | doc }} + +{{ "ExampleList" | example }} + +# Keywords +[Identifiers](#identifiers) **Keywords** [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +Simple keywords, predeclared identifiers and built-in functions are self +explanatory: + +| Construct | Name | +| ---------------- | ---- | +| Keywords | Break, Chan, Const, Continue, Default, Defer, Else, Fallthrough, Func, Go, Goto, Range, Select, Type, Var | +| Functions | Append, Cap, Close, Complex, Copy, Delete, Imag, Len, Make, New, Panic, Print, Println, Real, Recover | +| Types | Bool, Byte, Complex64, Complex128, Error, Float32, Float64, Int, Int8, Int16, Int32, Int64, Rune, String, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr | +| Constants | True, False, Iota, Nil | +| Helpers | Err | + +Built-in functions take a list of parameters and render them appropriately: + +{{ "ExampleAppend_more" | example }} + +Special cases for [If, For](#if-for), [Interface, Struct](#interface-struct), [Switch, Case](#switch-select), [Return](#return) and [Map](#map) are explained below. + +# Operators +[Identifiers](#identifiers) [Keywords](#keywords) **Operators** [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +{{ "Op" | doc }} + +{{ "ExampleOp" | example }} + +{{ "ExampleOp_star" | example }} + +{{ "ExampleOp_variadic" | example }} + +{{ "ExampleOp_complex_conditions" | example }} + +# Braces +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) **Braces** [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +Several methods render curly braces, summarized below: + +| Name | Prefix | Separator | Example | +| ------------------------------ | ------------ | --------- | -------------------------------------| +| [Block](#block) | | `\n` | `func a() { ... }` or `if a { ... }` | +| [Interface](#interface-struct) | `interface` | `\n` | `interface { ... }` | +| [Struct](#interface-struct) | `struct` | `\n` | `struct { ... }` | +| [Values](#values) | | `,` | `[]int{1, 2}` or `A{B: "c"}` | + +### Block +{{ "Block[:2]" | doc }} + +{{ "ExampleBlock" | example }} + +{{ "ExampleBlock_if" | example }} + +{{ "Block[2:]" | doc }} [See example](#switch-select). + +### Interface, Struct +Interface and Struct render the keyword followed by a statement list enclosed +by curly braces. + +{{ "ExampleInterface_empty" | example }} + +{{ "ExampleInterface" | example }} + +{{ "ExampleStruct_empty" | example }} + +{{ "ExampleStruct" | example }} + +# Parentheses +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) **Parentheses** [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +Several methods output parenthesis, summarized below: + +| Name | Prefix | Separator | Example | +| ----------------- | ------ | --------- | --------------------------------- | +| [Call](#call) | | `,` | `fmt.Println(b, c)` | +| [Params](#params) | | `,` | `func (a *A) Foo(i int) { ... }` | +| [Defs](#defs) | | `\n` | `const ( ... )` | +| [Parens](#parens) | | | `[]byte(s)` or `a / (b + c)` | +| [Assert](#assert) | `.` | | `s, ok := i.(string)` | + +### Call +{{ "Call" | doc }} + +{{ "ExampleCall" | example }} + +### Params +{{ "Params" | doc }} + +{{ "ExampleParams" | example }} + +### Defs +{{ "Defs" | doc }} + +{{ "ExampleDefs" | example }} + +### Parens +{{ "Parens" | doc }} + +{{ "ExampleParens" | example }} + +{{ "ExampleParens_order" | example }} + +### Assert +{{ "Assert" | doc }} + +{{ "ExampleAssert" | example }} + +# Control flow +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) **Control flow** [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +### If, For +If and For render the keyword followed by a semicolon separated list. + +{{ "ExampleIf" | example }} + +{{ "ExampleFor" | example }} + +### Switch, Select +Switch, Select, Case and Block are used to build switch or select statements: + +{{ "ExampleSwitch" | example }} + +### Return +{{ "Return" | doc }} + +{{ "ExampleReturn" | example }} + +# Collections +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) **Collections** [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +### Map +{{ "Map" | doc }} + +{{ "ExampleMap" | example }} + +### Index +{{ "Index" | doc }} + +{{ "ExampleIndex" | example }} + +{{ "ExampleIndex_index" | example }} + +{{ "ExampleIndex_empty" | example }} + +### Values +{{ "Values" | doc }} + +{{ "ExampleValues" | example }} + +{{ "Dict" | doc }} + +{{ "ExampleValues_dict_multiple" | example }} + +{{ "ExampleValues_dict_composite" | example }} + +{{ "DictFunc[0]" | doc }} + +{{ "ExampleDictFunc" | example }} + +Note: the items are ordered by key when rendered to ensure repeatable code. + +# Literals +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) **Literals** [Comments](#comments) [Helpers](#helpers) [Misc](#misc) [File](#file) + +### Lit +{{ "Lit" | doc }} + +{{ "ExampleLit" | example }} + +{{ "ExampleLit_float" | example }} + +{{ "LitFunc[1:2]" | doc }} + +{{ "ExampleLitFunc" | example }} + +For the default constant types (bool, int, float64, string, complex128), Lit +will render the untyped constant. + +| Code | Output | +| ------------- | ---------- | +| `Lit(true)` | `true` | +| `Lit(1)` | `1` | +| `Lit(1.0)` | `1.0` | +| `Lit("foo")` | `"foo"` | +| `Lit(0 + 1i)` | `(0 + 1i)` | + +For all other built-in types (float32, int8, int16, int32, int64, uint, uint8, +uint16, uint32, uint64, uintptr, complex64), Lit will also render the type. + +| Code | Output | +| ------------------------ | ------------------- | +| `Lit(float32(1))` | `float32(1)` | +| `Lit(int16(1))` | `int16(1)` | +| `Lit(uint8(0x1))` | `uint8(0x1)` | +| `Lit(complex64(0 + 1i))` | `complex64(0 + 1i)` | + +The built-in alias types byte and rune need a special case. LitRune and LitByte +render rune and byte literals. + +| Code | Output | +| ------------------------ | ----------- | +| `LitRune('x')` | `'x'` | +| `LitByte(byte(0x1))` | `byte(0x1)` | + +# Comments +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) **Comments** [Helpers](#helpers) [Misc](#misc) [File](#file) + +### Comment +{{ "Comment[:2]" | doc }} + +{{ "ExampleComment" | example }} + +{{ "ExampleComment_multiline" | example }} + +{{ "Comment[2:]" | doc }} + +{{ "ExampleComment_formatting_disabled" | example }} + +### Commentf +{{ "Commentf[0]" | doc }} + +{{ "ExampleCommentf" | example }} + +# Helpers +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) **Helpers** [Misc](#misc) [File](#file) + +### Func methods +All constructs that accept a variadic list of items are paired with GroupFunc +functions that accept a func(*Group). Use for embedding logic. + +{{ "ExampleValuesFunc" | example }} + +{{ "ExampleBlockFunc" | example }} + +### Add +{{ "Add" | doc }} + +{{ "ExampleAdd" | example }} + +{{ "ExampleAdd_var" | example }} + +### Do +{{ "Do" | doc }} + +{{ "ExampleDo" | example }} + +# Misc +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) **Misc** [File](#file) + +### Tag +{{ "Tag" | doc }} + +{{ "ExampleTag" | example }} + +Note: the items are ordered by key when rendered to ensure repeatable code. + +### Null +{{ "Null" | doc }} + +In lists, nil will produce the same effect. + +{{ "ExampleNull_and_nil" | example }} + +### Empty +{{ "Empty" | doc }} + +{{ "ExampleEmpty" | example }} + +### Line +{{ "Line" | doc }} + +### Clone +Be careful when passing *Statement. Consider the following... + +{{ "ExampleStatement_Clone_broken" | example }} + +Id("a") returns a *Statement, which the Call() method appends to twice. To +avoid this, use Clone. {{ "Statement.Clone" | doc }} + +{{ "ExampleStatement_Clone_fixed" | example }} + +### Cgo +The cgo "C" pseudo-package is a special case, and always renders without a package alias. The +import can be added with `Qual`, `Anon` or by supplying a preamble. The preamble is added with +`File.CgoPreamble` which has the same semantics as [Comment](#comments). If a preamble is provided, +the import is separated, and preceded by the preamble. + +{{ "ExampleFile_CgoPreamble" | example }} + +# File +[Identifiers](#identifiers) [Keywords](#keywords) [Operators](#operators) [Braces](#braces) [Parentheses](#parentheses) [Control flow](#control-flow) [Collections](#collections) [Literals](#literals) [Comments](#comments) [Helpers](#helpers) [Misc](#misc) **File** + +{{ "File" | doc }} + +### NewFile +{{ "NewFile" | doc }} + +### NewFilePath +{{ "NewFilePath" | doc }} + +### NewFilePathName +{{ "NewFilePathName" | doc }} + +{{ "ExampleNewFilePathName" | example }} + +### Save +{{ "File.Save" | doc }} + +### Render +{{ "File.Render" | doc }} + +{{ "ExampleFile_Render" | example }} + +### Anon +{{ "File.Anon" | doc }} + +{{ "ExampleFile_Anon" | example }} + +### ImportName +{{ "File.ImportName" | doc }} + +{{ "ExampleFile_ImportName" | example }} + +### ImportNames +{{ "File.ImportNames" | doc }} + +### ImportAlias +{{ "File.ImportAlias" | doc }} + +{{ "ExampleFile_ImportAlias" | example }} + +### Comments +{{ "File.PackageComment" | doc }} + +{{ "File.HeaderComment" | doc }} + +{{ "File.CanonicalPath" | doc }} + +{{ "ExampleFile_HeaderAndPackageComments" | example }} + +{{ "File.CgoPreamble" | doc }} + +### PackagePrefix +{{ "File.PackagePrefix" | doc }} + +{{ "ExampleFile_PackagePrefix" | example }} diff --git a/vendor/github.com/dave/jennifer/genjen/data.go b/vendor/github.com/dave/jennifer/genjen/data.go new file mode 100644 index 00000000..ff8b39a7 --- /dev/null +++ b/vendor/github.com/dave/jennifer/genjen/data.go @@ -0,0 +1,307 @@ +package main + +var keywords = []string{"break", "default", "func", "select", "chan", "else", "const", "fallthrough", "type", "continue", "var", "goto", "defer", "go", "range"} + +var identifiers = []string{"bool", "byte", "complex64", "complex128", "error", "float32", "float64", "int", "int8", "int16", "int32", "int64", "rune", "string", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "true", "false", "iota", "nil", "err"} + +var groups = []struct { + name string // name of the function / method + comment string // comment appended to name + variadic bool // is the parameter variadic? + opening string // opening token + closing string // closing token + separator string // separator token + multi bool // items are always on multiple lines + parameters []string // parameter names + preventFunc bool // prevent the fooFunc function/method +}{ + { + name: "Parens", + comment: "renders a single item in parenthesis. Use for type conversion or to specify evaluation order.", + variadic: false, + opening: "(", + closing: ")", + separator: "", + parameters: []string{"item"}, + }, + { + name: "List", + comment: "renders a comma separated list. Use for multiple return functions.", + variadic: true, + opening: "", + closing: "", + separator: ",", + parameters: []string{"items"}, + }, + { + name: "Values", + comment: "renders a comma separated list enclosed by curly braces. Use for slice or composite literals.", + variadic: true, + opening: "{", + closing: "}", + separator: ",", + parameters: []string{"values"}, + }, + { + name: "Index", + comment: "renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions.", + variadic: true, + opening: "[", + closing: "]", + separator: ":", + parameters: []string{"items"}, + }, + { + name: "Block", + comment: "renders a statement list enclosed by curly braces. Use for code blocks. A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements.", + variadic: true, + opening: "{", + closing: "}", + multi: true, + parameters: []string{"statements"}, + }, + { + name: "Defs", + comment: "renders a statement list enclosed in parenthesis. Use for definition lists.", + variadic: true, + opening: "(", + closing: ")", + multi: true, + parameters: []string{"definitions"}, + }, + { + name: "Call", + comment: "renders a comma separated list enclosed by parenthesis. Use for function calls.", + variadic: true, + opening: "(", + closing: ")", + separator: ",", + parameters: []string{"params"}, + }, + { + name: "Params", + comment: "renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers.", + variadic: true, + opening: "(", + closing: ")", + separator: ",", + parameters: []string{"params"}, + }, + { + name: "Assert", + comment: "renders a period followed by a single item enclosed by parenthesis. Use for type assertions.", + variadic: false, + opening: ".(", + closing: ")", + separator: "", + parameters: []string{"typ"}, + }, + { + name: "Map", + comment: "renders the keyword followed by a single item enclosed by square brackets. Use for map definitions.", + variadic: false, + opening: "map[", + closing: "]", + separator: "", + parameters: []string{"typ"}, + }, + { + name: "If", + comment: "renders the keyword followed by a semicolon separated list.", + variadic: true, + opening: "if ", + closing: "", + separator: ";", + parameters: []string{"conditions"}, + }, + { + name: "Return", + comment: "renders the keyword followed by a comma separated list.", + variadic: true, + opening: "return ", + closing: "", + separator: ",", + parameters: []string{"results"}, + }, + { + name: "For", + comment: "renders the keyword followed by a semicolon separated list.", + variadic: true, + opening: "for ", + closing: "", + separator: ";", + parameters: []string{"conditions"}, + }, + { + name: "Switch", + comment: "renders the keyword followed by a semicolon separated list.", + variadic: true, + opening: "switch ", + closing: "", + separator: ";", + parameters: []string{"conditions"}, + }, + { + name: "Interface", + comment: "renders the keyword followed by a method list enclosed by curly braces.", + variadic: true, + opening: "interface{", + closing: "}", + multi: true, + parameters: []string{"methods"}, + }, + { + name: "Struct", + comment: "renders the keyword followed by a field list enclosed by curly braces.", + variadic: true, + opening: "struct{", + closing: "}", + multi: true, + parameters: []string{"fields"}, + }, + { + name: "Case", + comment: "renders the keyword followed by a comma separated list.", + variadic: true, + opening: "case ", + closing: ":", + separator: ",", + parameters: []string{"cases"}, + }, + { + name: "Append", + comment: "renders the append built-in function.", + variadic: true, + opening: "append(", + closing: ")", + separator: ",", + parameters: []string{"args"}, + }, + { + name: "Cap", + comment: "renders the cap built-in function.", + variadic: false, + opening: "cap(", + closing: ")", + separator: ",", + parameters: []string{"v"}, + }, + { + name: "Close", + comment: "renders the close built-in function.", + variadic: false, + opening: "close(", + closing: ")", + separator: ",", + parameters: []string{"c"}, + }, + { + name: "Complex", + comment: "renders the complex built-in function.", + variadic: false, + opening: "complex(", + closing: ")", + separator: ",", + parameters: []string{"r", "i"}, + }, + { + name: "Copy", + comment: "renders the copy built-in function.", + variadic: false, + opening: "copy(", + closing: ")", + separator: ",", + parameters: []string{"dst", "src"}, + }, + { + name: "Delete", + comment: "renders the delete built-in function.", + variadic: false, + opening: "delete(", + closing: ")", + separator: ",", + parameters: []string{"m", "key"}, + }, + { + name: "Imag", + comment: "renders the imag built-in function.", + variadic: false, + opening: "imag(", + closing: ")", + separator: ",", + parameters: []string{"c"}, + }, + { + name: "Len", + comment: "renders the len built-in function.", + variadic: false, + opening: "len(", + closing: ")", + separator: ",", + parameters: []string{"v"}, + }, + { + name: "Make", + comment: "renders the make built-in function. The final parameter of the make function is optional, so it is represented by a variadic parameter list.", + variadic: true, + opening: "make(", + closing: ")", + separator: ",", + parameters: []string{"args"}, + preventFunc: true, // the underlying function is not variadic, so we prevent the MakeFunc variation + }, + { + name: "New", + comment: "renders the new built-in function.", + variadic: false, + opening: "new(", + closing: ")", + separator: ",", + parameters: []string{"typ"}, + }, + { + name: "Panic", + comment: "renders the panic built-in function.", + variadic: false, + opening: "panic(", + closing: ")", + separator: ",", + parameters: []string{"v"}, + }, + { + name: "Print", + comment: "renders the print built-in function.", + variadic: true, + opening: "print(", + closing: ")", + separator: ",", + parameters: []string{"args"}, + }, + { + name: "Println", + comment: "renders the println built-in function.", + variadic: true, + opening: "println(", + closing: ")", + separator: ",", + parameters: []string{"args"}, + }, + { + name: "Real", + comment: "renders the real built-in function.", + variadic: false, + opening: "real(", + closing: ")", + separator: ",", + parameters: []string{"c"}, + }, + { + name: "Recover", + comment: "renders the recover built-in function.", + variadic: false, + opening: "recover(", + closing: ")", + separator: ",", + parameters: []string{}, + }, +} diff --git a/vendor/github.com/dave/jennifer/genjen/main.go b/vendor/github.com/dave/jennifer/genjen/main.go new file mode 100644 index 00000000..ff73434c --- /dev/null +++ b/vendor/github.com/dave/jennifer/genjen/main.go @@ -0,0 +1,17 @@ +package main + +import ( + "bytes" + "io/ioutil" +) + +func main() { + // notest + buf := &bytes.Buffer{} + if err := render(buf); err != nil { + panic(err) + } + if err := ioutil.WriteFile("./jen/generated.go", buf.Bytes(), 0644); err != nil { + panic(err) + } +} diff --git a/vendor/github.com/dave/jennifer/genjen/render.go b/vendor/github.com/dave/jennifer/genjen/render.go new file mode 100644 index 00000000..3ab0e93a --- /dev/null +++ b/vendor/github.com/dave/jennifer/genjen/render.go @@ -0,0 +1,260 @@ +package main + +import ( + "io" + "strings" + + . "github.com/dave/jennifer/jen" +) + +func render(w io.Writer) error { + file := NewFile("jen") + + file.HeaderComment("This file is generated - do not edit.") + file.Line() + + for _, b := range groups { + b := b // b used in closures + comment := Commentf("%s %s", b.name, b.comment) + + if b.variadic && len(b.parameters) > 1 { + panic("should not have variadic function with multiple params") + } + + var variadic Code + if b.variadic { + variadic = Op("...") + } + var funcParams []Code + var callParams []Code + for _, name := range b.parameters { + funcParams = append(funcParams, Id(name).Add(variadic).Id("Code")) + callParams = append(callParams, Id(name).Add(variadic)) + } + + addFunctionAndGroupMethod( + file, + b.name, + comment, + funcParams, + callParams, + false, + ) + + /* + // + func (s *Statement) () *Statement { + g := &Group{ + items: []Code{}|, + name: "", + open: "", + close: "", + separator: "", + multi: , + } + *s = append(*s, g) + return s + } + */ + file.Add(comment) + file.Func().Params( + Id("s").Op("*").Id("Statement"), + ).Id(b.name).Params( + funcParams..., + ).Op("*").Id("Statement").Block( + Id("g").Op(":=").Op("&").Id("Group").Values(Dict{ + Id("items"): Do(func(s *Statement) { + if b.variadic { + s.Id(b.parameters[0]) + } else { + s.Index().Id("Code").ValuesFunc(func(g *Group) { + for _, name := range b.parameters { + g.Id(name) + } + }) + } + }), + Id("name"): Lit(strings.ToLower(b.name)), + Id("open"): Lit(b.opening), + Id("close"): Lit(b.closing), + Id("separator"): Lit(b.separator), + Id("multi"): Lit(b.multi), + }), + Op("*").Id("s").Op("=").Append(Op("*").Id("s"), Id("g")), + Return(Id("s")), + ) + + if b.variadic && !b.preventFunc { + + funcName := b.name + "Func" + funcComment := Commentf("%sFunc %s", b.name, b.comment) + funcFuncParams := []Code{Id("f").Func().Params(Op("*").Id("Group"))} + funcCallParams := []Code{Id("f")} + + addFunctionAndGroupMethod( + file, + funcName, + funcComment, + funcFuncParams, + funcCallParams, + false, + ) + + /* + // + func (s *Statement) (f func(*Group)) *Statement { + g := &Group{ + name: "", + open: "", + close: "", + separator: "", + multi: , + } + f(g) + *s = append(*s, g) + return s + } + */ + file.Add(funcComment) + file.Func().Params( + Id("s").Op("*").Id("Statement"), + ).Id(funcName).Params( + funcFuncParams..., + ).Op("*").Id("Statement").Block( + Id("g").Op(":=").Op("&").Id("Group").Values(Dict{ + Id("name"): Lit(strings.ToLower(b.name)), + Id("open"): Lit(b.opening), + Id("close"): Lit(b.closing), + Id("separator"): Lit(b.separator), + Id("multi"): Lit(b.multi), + }), + Id("f").Call(Id("g")), + Op("*").Id("s").Op("=").Append(Op("*").Id("s"), Id("g")), + Return(Id("s")), + ) + } + } + + type tkn struct { + token string + name string + tokenType string + tokenDesc string + } + tokens := []tkn{} + for _, v := range identifiers { + tokens = append(tokens, tkn{ + token: v, + name: strings.ToUpper(v[:1]) + v[1:], + tokenType: "identifierToken", + tokenDesc: "identifier", + }) + } + for _, v := range keywords { + tokens = append(tokens, tkn{ + token: v, + name: strings.ToUpper(v[:1]) + v[1:], + tokenType: "keywordToken", + tokenDesc: "keyword", + }) + } + + for i, t := range tokens { + t := t // used in closures + comment := Commentf( + "%s renders the %s %s.", + t.name, + t.token, + t.tokenDesc, + ) + addFunctionAndGroupMethod( + file, + t.name, + comment, + nil, + nil, + i != 0, // only enforce test coverage on one item + ) + + /* + // + func (s *Statement) () *Statement { + t := token{ + typ: , + content: "", + } + *s = append(*s, t) + return s + } + */ + file.Add(comment) + file.Func().Params( + Id("s").Op("*").Id("Statement"), + ).Id(t.name).Params().Op("*").Id("Statement").Block( + Do(func(s *Statement) { + if i != 0 { + // only enforce test coverage on one item + s.Comment("notest") + } + }), + Id("t").Op(":=").Id("token").Values(Dict{ + Id("typ"): Id(t.tokenType), + Id("content"): Lit(t.token), + }), + Op("*").Id("s").Op("=").Append(Op("*").Id("s"), Id("t")), + Return(Id("s")), + ) + } + + return file.Render(w) +} + +// For each method on *Statement, this generates a package level +// function and a method on *Group, both with the same name. +func addFunctionAndGroupMethod( + file *File, + name string, + comment *Statement, + funcParams []Code, + callParams []Code, + notest bool, +) { + /* + // + func () *Statement { + return newStatement().() + } + */ + file.Add(comment) + file.Func().Id(name).Params(funcParams...).Op("*").Id("Statement").Block( + Do(func(s *Statement) { + if notest { + // only enforce test coverage on one item + s.Comment("notest") + } + }), + Return(Id("newStatement").Call().Dot(name).Call(callParams...)), + ) + /* + // + func (g *Group) () *Statement { + s := () + g.items = append(g.items, s) + return s + } + */ + file.Add(comment) + file.Func().Params( + Id("g").Op("*").Id("Group"), + ).Id(name).Params(funcParams...).Op("*").Id("Statement").Block( + Do(func(s *Statement) { + if notest { + // only enforce test coverage on one item + s.Comment("notest") + } + }), + Id("s").Op(":=").Id(name).Params(callParams...), + Id("g").Dot("items").Op("=").Append(Id("g").Dot("items"), Id("s")), + Return(Id("s")), + ) +} diff --git a/vendor/github.com/dave/jennifer/genjen/render_test.go b/vendor/github.com/dave/jennifer/genjen/render_test.go new file mode 100644 index 00000000..2b549d91 --- /dev/null +++ b/vendor/github.com/dave/jennifer/genjen/render_test.go @@ -0,0 +1,35 @@ +package main + +import ( + "io/ioutil" + "regexp" + "testing" + + "bytes" +) + +func TestRender(t *testing.T) { + + buf := &bytes.Buffer{} + if err := render(buf); err != nil { + t.Fatal(err.Error()) + } + generatedString := buf.String() + + existingFilePath := "../jen/generated.go" + existingBytes, err := ioutil.ReadFile(existingFilePath) + if err != nil { + t.Fatal(err.Error()) + } + existingString := string(existingBytes) + + // The "goimports" tool will often re-order the imports, so this is a + // kludge to remove it before comparing. This is not ideal! + importsRegex := regexp.MustCompile(`(?ms:\nimport \(\n.*\n\)\n)`) + generatedString = importsRegex.ReplaceAllString(generatedString, "-") + existingString = importsRegex.ReplaceAllString(existingString, "-") + + if generatedString != existingString { + t.Fatalf("Generated code is not what is present:\n%s", generatedString) + } +} diff --git a/vendor/github.com/dave/jennifer/gennames/README.md b/vendor/github.com/dave/jennifer/gennames/README.md new file mode 100644 index 00000000..ef60cfe0 --- /dev/null +++ b/vendor/github.com/dave/jennifer/gennames/README.md @@ -0,0 +1,52 @@ +# gennames +For large projects, it may be useful to generate an index of package names for commonly used packages. +The index of names can be added to each generated file using `File.ImportNames`. The `gennames` command +is used internally to generate the list of standard library package names. + +### Usage + +``` +Usage of gennames: + -filter string + Regex to filter paths (operates on full path including vendor directory) (default ".*") + -name string + Name of the variable to define (default "PackageNames") + -novendor + Exclude packages in vendor directories + -output string + Output filename to write (default "./package-names.go") + -package string + Package name in generated file (default "main") + -path string + Path to pass to go list command (default "all") + -standard + Use standard library packages +``` + +### Path +Supply a `path` to pass to the `go list` command. You may use the wildcard `/...` to recursively return +packages, but it's worth remembering that vendored packages are not returned by this method unless the +path itself is a vendored path. Use `all` to return all packages in your `GOPATH` (including vendored +packages), however remember this may take some time for a large `GOPATH`. + +### Filter +Supply a regex `filter` to limit the packages that are returned by the `go list` command. The filter +operates on the full vendored package path (e.g. `github.com/foo/bar/vendor/github.com/baz/qux`), however +the package path added to the index is unvendored (e.g. `github.com/baz/qux`). + +### Examples + +``` +gennames -filter "foo|bar" +``` + +Create a file named `package-names.go` with `package main` listing the names of all packages with paths +containing `foo` or `bar`. + +``` +gennames -output "foo/names.go" -package "foo" -path "github.com/foo/bar/vendor/..." +``` + +Create a file named `foo/names.go` with `package foo` listing the names of all packages that are vendored +inside `github.com/foo/bar`. + diff --git a/vendor/github.com/dave/jennifer/gennames/hints.go b/vendor/github.com/dave/jennifer/gennames/hints.go new file mode 100644 index 00000000..51288f1e --- /dev/null +++ b/vendor/github.com/dave/jennifer/gennames/hints.go @@ -0,0 +1,141 @@ +package main + +import ( + "fmt" + "go/build" + "io" + "os/exec" + "strings" + + "regexp" + + "path/filepath" + + . "github.com/dave/jennifer/jen" +) + +func hints(w io.Writer, pkg, name, goListPath, filter string, standard, novendor bool) error { + + // notest + + file := NewFile(pkg) + + file.HeaderComment("This file is generated - do not edit.") + file.Line() + + packages, err := getPackages(goListPath, filter, standard, novendor) + if err != nil { + return err + } + /* + // contains package name hints + var = map[string]string{ + ... + } + */ + file.Commentf("%s contains package name hints", name) + file.Var().Id(name).Op("=").Map(String()).String().Values(DictFunc(func(d Dict) { + for path, name := range packages { + d[Lit(path)] = Lit(name) + } + })) + + return file.Render(w) +} + +func getPackages(goListPath, filter string, standard, novendor bool) (map[string]string, error) { + + // notest + + r, err := regexp.Compile(filter) + if err != nil { + return nil, err + } + + cmd := exec.Command("go", "list", "-e", "-f", "{{ .Standard }} {{ .ImportPath }} {{ .Name }}", goListPath) + cmd.Env = []string{ + fmt.Sprintf("GOPATH=%s", build.Default.GOPATH), + fmt.Sprintf("GOROOT=%s", build.Default.GOROOT), + } + if standard { + cmd.Dir = filepath.Join(build.Default.GOROOT, "src") + } else { + cmd.Dir = filepath.Join(build.Default.GOPATH, "src") + } + b, err := cmd.Output() + if err != nil { + if x, ok := err.(*exec.ExitError); ok { + return nil, fmt.Errorf("go list command returned an error - %s: %s", err.Error(), string(x.Stderr)) + } + return nil, fmt.Errorf("go list command returned an error: %s", err.Error()) + } + all := strings.Split(strings.TrimSpace(string(b)), "\n") + + packages := map[string]string{} + for _, j := range all { + + parts := strings.Split(j, " ") + + isStandard := parts[0] == "true" + if isStandard != standard { + continue + } + + path := parts[1] + name := parts[2] + + if novendor && hasVendor(path) { + continue + } + + if name == "main" { + continue + } + + if !r.MatchString(path) { + continue + } + + path = unvendorPath(path) + + if packages[path] != "" { + continue + } + + packages[path] = name + } + return packages, nil +} + +func unvendorPath(path string) string { + // notest + i, ok := findVendor(path) + if !ok { + return path + } + return path[i+len("vendor/"):] +} + +// FindVendor looks for the last non-terminating "vendor" path element in the given import path. +// If there isn't one, FindVendor returns ok=false. +// Otherwise, FindVendor returns ok=true and the index of the "vendor". +// Copied from cmd/go/internal/load +func findVendor(path string) (index int, ok bool) { + // notest + // Two cases, depending on internal at start of string or not. + // The order matters: we must return the index of the final element, + // because the final one is where the effective import path starts. + switch { + case strings.Contains(path, "/vendor/"): + return strings.LastIndex(path, "/vendor/") + 1, true + case strings.HasPrefix(path, "vendor/"): + return 0, true + } + return 0, false +} + +func hasVendor(path string) bool { + // notest + _, v := findVendor(path) + return v +} diff --git a/vendor/github.com/dave/jennifer/gennames/main.go b/vendor/github.com/dave/jennifer/gennames/main.go new file mode 100644 index 00000000..1ff8e51a --- /dev/null +++ b/vendor/github.com/dave/jennifer/gennames/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "bytes" + "flag" + "io/ioutil" + "log" +) + +func main() { + // notest + + var out = flag.String("output", "./package-names.go", "Output filename to write") + var pkg = flag.String("package", "main", "Package name in generated file") + var name = flag.String("name", "PackageNames", "Name of the variable to define") + var filter = flag.String("filter", ".*", "Regex to filter paths (operates on full path including vendor directory)") + var standard = flag.Bool("standard", false, "Use standard library packages") + var novendor = flag.Bool("novendor", false, "Exclude packages in vendor directories") + var goListPath = flag.String("path", "all", "Path to pass to go list command") + flag.Parse() + + buf := &bytes.Buffer{} + if err := hints(buf, *pkg, *name, *goListPath, *filter, *standard, *novendor); err != nil { + log.Fatal(err.Error()) + } + if err := ioutil.WriteFile(*out, buf.Bytes(), 0644); err != nil { + log.Fatal(err.Error()) + } +} diff --git a/vendor/github.com/dave/jennifer/jen/add.go b/vendor/github.com/dave/jennifer/jen/add.go new file mode 100644 index 00000000..2efb3f6d --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/add.go @@ -0,0 +1,19 @@ +package jen + +// Add appends the provided items to the statement. +func Add(code ...Code) *Statement { + return newStatement().Add(code...) +} + +// Add appends the provided items to the statement. +func (g *Group) Add(code ...Code) *Statement { + s := Add(code...) + g.items = append(g.items, s) + return s +} + +// Add appends the provided items to the statement. +func (s *Statement) Add(code ...Code) *Statement { + *s = append(*s, code...) + return s +} diff --git a/vendor/github.com/dave/jennifer/jen/comments.go b/vendor/github.com/dave/jennifer/jen/comments.go new file mode 100644 index 00000000..886e885b --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/comments.go @@ -0,0 +1,108 @@ +package jen + +import ( + "fmt" + "io" + "strings" +) + +// Comment adds a comment. If the provided string contains a newline, the +// comment is formatted in multiline style. If the comment string starts +// with "//" or "/*", the automatic formatting is disabled and the string is +// rendered directly. +func Comment(str string) *Statement { + return newStatement().Comment(str) +} + +// Comment adds a comment. If the provided string contains a newline, the +// comment is formatted in multiline style. If the comment string starts +// with "//" or "/*", the automatic formatting is disabled and the string is +// rendered directly. +func (g *Group) Comment(str string) *Statement { + s := Comment(str) + g.items = append(g.items, s) + return s +} + +// Comment adds a comment. If the provided string contains a newline, the +// comment is formatted in multiline style. If the comment string starts +// with "//" or "/*", the automatic formatting is disabled and the string is +// rendered directly. +func (s *Statement) Comment(str string) *Statement { + c := comment{ + comment: str, + } + *s = append(*s, c) + return s +} + +// Commentf adds a comment, using a format string and a list of parameters. If +// the provided string contains a newline, the comment is formatted in +// multiline style. If the comment string starts with "//" or "/*", the +// automatic formatting is disabled and the string is rendered directly. +func Commentf(format string, a ...interface{}) *Statement { + return newStatement().Commentf(format, a...) +} + +// Commentf adds a comment, using a format string and a list of parameters. If +// the provided string contains a newline, the comment is formatted in +// multiline style. If the comment string starts with "//" or "/*", the +// automatic formatting is disabled and the string is rendered directly. +func (g *Group) Commentf(format string, a ...interface{}) *Statement { + s := Commentf(format, a...) + g.items = append(g.items, s) + return s +} + +// Commentf adds a comment, using a format string and a list of parameters. If +// the provided string contains a newline, the comment is formatted in +// multiline style. If the comment string starts with "//" or "/*", the +// automatic formatting is disabled and the string is rendered directly. +func (s *Statement) Commentf(format string, a ...interface{}) *Statement { + c := comment{ + comment: fmt.Sprintf(format, a...), + } + *s = append(*s, c) + return s +} + +type comment struct { + comment string +} + +func (c comment) isNull(f *File) bool { + return false +} + +func (c comment) render(f *File, w io.Writer, s *Statement) error { + if strings.HasPrefix(c.comment, "//") || strings.HasPrefix(c.comment, "/*") { + // automatic formatting disabled. + if _, err := w.Write([]byte(c.comment)); err != nil { + return err + } + return nil + } + if strings.Contains(c.comment, "\n") { + if _, err := w.Write([]byte("/*\n")); err != nil { + return err + } + } else { + if _, err := w.Write([]byte("// ")); err != nil { + return err + } + } + if _, err := w.Write([]byte(c.comment)); err != nil { + return err + } + if strings.Contains(c.comment, "\n") { + if !strings.HasSuffix(c.comment, "\n") { + if _, err := w.Write([]byte("\n")); err != nil { + return err + } + } + if _, err := w.Write([]byte("*/")); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/dave/jennifer/jen/custom.go b/vendor/github.com/dave/jennifer/jen/custom.go new file mode 100644 index 00000000..4966a070 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/custom.go @@ -0,0 +1,61 @@ +package jen + +// Options specifies options for the Custom method +type Options struct { + Open string + Close string + Separator string + Multi bool +} + +// Custom renders a customized statement list. Pass in options to specify multi-line, and tokens for open, close, separator. +func Custom(options Options, statements ...Code) *Statement { + return newStatement().Custom(options, statements...) +} + +// Custom renders a customized statement list. Pass in options to specify multi-line, and tokens for open, close, separator. +func (g *Group) Custom(options Options, statements ...Code) *Statement { + s := Custom(options, statements...) + g.items = append(g.items, s) + return s +} + +// Custom renders a customized statement list. Pass in options to specify multi-line, and tokens for open, close, separator. +func (s *Statement) Custom(options Options, statements ...Code) *Statement { + g := &Group{ + close: options.Close, + items: statements, + multi: options.Multi, + name: "custom", + open: options.Open, + separator: options.Separator, + } + *s = append(*s, g) + return s +} + +// CustomFunc renders a customized statement list. Pass in options to specify multi-line, and tokens for open, close, separator. +func CustomFunc(options Options, f func(*Group)) *Statement { + return newStatement().CustomFunc(options, f) +} + +// CustomFunc renders a customized statement list. Pass in options to specify multi-line, and tokens for open, close, separator. +func (g *Group) CustomFunc(options Options, f func(*Group)) *Statement { + s := CustomFunc(options, f) + g.items = append(g.items, s) + return s +} + +// CustomFunc renders a customized statement list. Pass in options to specify multi-line, and tokens for open, close, separator. +func (s *Statement) CustomFunc(options Options, f func(*Group)) *Statement { + g := &Group{ + close: options.Close, + multi: options.Multi, + name: "custom", + open: options.Open, + separator: options.Separator, + } + f(g) + *s = append(*s, g) + return s +} diff --git a/vendor/github.com/dave/jennifer/jen/dict.go b/vendor/github.com/dave/jennifer/jen/dict.go new file mode 100644 index 00000000..260cf928 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/dict.go @@ -0,0 +1,81 @@ +package jen + +import ( + "bytes" + "io" + "sort" +) + +// Dict renders as key/value pairs. Use with Values for map or composite +// literals. +type Dict map[Code]Code + +// DictFunc executes a func(Dict) to generate the value. Use with Values for +// map or composite literals. +func DictFunc(f func(Dict)) Dict { + d := Dict{} + f(d) + return d +} + +func (d Dict) render(f *File, w io.Writer, s *Statement) error { + first := true + // must order keys to ensure repeatable source + type kv struct { + k Code + v Code + } + lookup := map[string]kv{} + keys := []string{} + for k, v := range d { + if k.isNull(f) || v.isNull(f) { + continue + } + buf := &bytes.Buffer{} + if err := k.render(f, buf, nil); err != nil { + return err + } + keys = append(keys, buf.String()) + lookup[buf.String()] = kv{k: k, v: v} + } + sort.Strings(keys) + for _, key := range keys { + k := lookup[key].k + v := lookup[key].v + if first && len(keys) > 1 { + if _, err := w.Write([]byte("\n")); err != nil { + return err + } + first = false + } + if err := k.render(f, w, nil); err != nil { + return err + } + if _, err := w.Write([]byte(":")); err != nil { + return err + } + if err := v.render(f, w, nil); err != nil { + return err + } + if len(keys) > 1 { + if _, err := w.Write([]byte(",\n")); err != nil { + return err + } + } + } + return nil +} + +func (d Dict) isNull(f *File) bool { + if d == nil || len(d) == 0 { + return true + } + for k, v := range d { + if !k.isNull(f) && !v.isNull(f) { + // if any of the key/value pairs are both not null, the Dict is not + // null + return false + } + } + return true +} diff --git a/vendor/github.com/dave/jennifer/jen/do.go b/vendor/github.com/dave/jennifer/jen/do.go new file mode 100644 index 00000000..c1bceab5 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/do.go @@ -0,0 +1,22 @@ +package jen + +// Do calls the provided function with the statement as a parameter. Use for +// embedding logic. +func Do(f func(*Statement)) *Statement { + return newStatement().Do(f) +} + +// Do calls the provided function with the statement as a parameter. Use for +// embedding logic. +func (g *Group) Do(f func(*Statement)) *Statement { + s := Do(f) + g.items = append(g.items, s) + return s +} + +// Do calls the provided function with the statement as a parameter. Use for +// embedding logic. +func (s *Statement) Do(f func(*Statement)) *Statement { + f(s) + return s +} diff --git a/vendor/github.com/dave/jennifer/jen/examples_test.go b/vendor/github.com/dave/jennifer/jen/examples_test.go new file mode 100644 index 00000000..d6316b5f --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/examples_test.go @@ -0,0 +1,1610 @@ +package jen_test + +import ( + "fmt" + + "bytes" + + . "github.com/dave/jennifer/jen" +) + +func ExampleCaseBug() { + c := Switch(Id("a")).Block( + Case(Lit(1)).Block( + Var().Id("i").Int(), + Var().Id("j").Int(), + ), + ) + fmt.Printf("%#v", c) + // Output: + // switch a { + // case 1: + // var i int + // var j int + // } +} + +func ExampleCustom() { + multiLineCall := Options{ + Close: ")", + Multi: true, + Open: "(", + Separator: ",", + } + c := Id("foo").Custom(multiLineCall, Lit("a"), Lit("b"), Lit("c")) + fmt.Printf("%#v", c) + // Output: + // foo( + // "a", + // "b", + // "c", + // ) +} + +func ExampleCustomFunc() { + multiLineCall := Options{ + Close: ")", + Multi: true, + Open: "(", + Separator: ",", + } + c := Id("foo").CustomFunc(multiLineCall, func(g *Group) { + g.Lit("a") + g.Lit("b") + g.Lit("c") + }) + fmt.Printf("%#v", c) + // Output: + // foo( + // "a", + // "b", + // "c", + // ) +} + +func ExampleFile_ImportName_conflict() { + f := NewFile("main") + + // We provide a hint that package foo/a should use name "a", but because package bar/a already + // registers the required name, foo/a is aliased. + f.ImportName("github.com/foo/a", "a") + + f.Func().Id("main").Params().Block( + Qual("github.com/bar/a", "Bar").Call(), + Qual("github.com/foo/a", "Foo").Call(), + ) + fmt.Printf("%#v", f) + + // Output: + // package main + // + // import ( + // a "github.com/bar/a" + // a1 "github.com/foo/a" + // ) + // + // func main() { + // a.Bar() + // a1.Foo() + // } +} + +func ExampleFile_ImportAlias_conflict() { + f := NewFile("main") + + // We provide a hint that package foo/a should use alias "b", but because package bar/b already + // registers the required name, foo/a is aliased using the requested alias as a base. + f.ImportName("github.com/foo/a", "b") + + f.Func().Id("main").Params().Block( + Qual("github.com/bar/b", "Bar").Call(), + Qual("github.com/foo/a", "Foo").Call(), + ) + fmt.Printf("%#v", f) + + // Output: + // package main + // + // import ( + // b "github.com/bar/b" + // b1 "github.com/foo/a" + // ) + // + // func main() { + // b.Bar() + // b1.Foo() + // } +} + +func ExampleFile_ImportName() { + f := NewFile("main") + + // package a should use name "a" + f.ImportName("github.com/foo/a", "a") + + // package b is not used in the code so will not be included + f.ImportName("github.com/foo/b", "b") + + f.Func().Id("main").Params().Block( + Qual("github.com/foo/a", "A").Call(), + ) + fmt.Printf("%#v", f) + + // Output: + // package main + // + // import "github.com/foo/a" + // + // func main() { + // a.A() + // } +} + +func ExampleFile_ImportNames() { + + // package a should use name "a", package b is not used in the code so will not be included + names := map[string]string{ + "github.com/foo/a": "a", + "github.com/foo/b": "b", + } + + f := NewFile("main") + f.ImportNames(names) + f.Func().Id("main").Params().Block( + Qual("github.com/foo/a", "A").Call(), + ) + fmt.Printf("%#v", f) + + // Output: + // package main + // + // import "github.com/foo/a" + // + // func main() { + // a.A() + // } +} + +func ExampleFile_ImportAlias() { + f := NewFile("main") + + // package a should be aliased to "b" + f.ImportAlias("github.com/foo/a", "b") + + // package c is not used in the code so will not be included + f.ImportAlias("github.com/foo/c", "c") + + f.Func().Id("main").Params().Block( + Qual("github.com/foo/a", "A").Call(), + ) + fmt.Printf("%#v", f) + + // Output: + // package main + // + // import b "github.com/foo/a" + // + // func main() { + // b.A() + // } +} + +func ExampleFile_ImportAliasDot() { + f := NewFile("main") + + // package a should be a dot-import + f.ImportAlias("github.com/foo/a", ".") + + // package b should be a dot-import + f.ImportAlias("github.com/foo/b", ".") + + // package c is not used in the code so will not be included + f.ImportAlias("github.com/foo/c", ".") + + f.Func().Id("main").Params().Block( + Qual("github.com/foo/a", "A").Call(), + Qual("github.com/foo/b", "B").Call(), + ) + fmt.Printf("%#v", f) + + // Output: + // package main + // + // import ( + // . "github.com/foo/a" + // . "github.com/foo/b" + // ) + // + // func main() { + // A() + // B() + // } +} + +func ExampleFile_CgoPreamble() { + f := NewFile("a") + f.CgoPreamble(`#include +#include + +void myprint(char* s) { + printf("%s\n", s); +} +`) + f.Func().Id("init").Params().Block( + Id("cs").Op(":=").Qual("C", "CString").Call(Lit("Hello from stdio\n")), + Qual("C", "myprint").Call(Id("cs")), + Qual("C", "free").Call(Qual("unsafe", "Pointer").Parens(Id("cs"))), + ) + fmt.Printf("%#v", f) + // Output: + // package a + // + // import "unsafe" + // + // /* + // #include + // #include + // + // void myprint(char* s) { + // printf("%s\n", s); + // } + // */ + // import "C" + // + // func init() { + // cs := C.CString("Hello from stdio\n") + // C.myprint(cs) + // C.free(unsafe.Pointer(cs)) + // } +} + +func ExampleFile_CgoPreamble_anon() { + f := NewFile("a") + f.CgoPreamble(`#include `) + f.Func().Id("init").Params().Block( + Qual("foo.bar/a", "A"), + Qual("foo.bar/b", "B"), + ) + fmt.Printf("%#v", f) + // Output: + // package a + // + // import ( + // a "foo.bar/a" + // b "foo.bar/b" + // ) + // + // // #include + // import "C" + // + // func init() { + // a.A + // b.B + // } +} + +func ExampleFile_CgoPreamble_no_preamble() { + f := NewFile("a") + f.Func().Id("init").Params().Block( + Qual("C", "Foo").Call(), + Qual("fmt", "Print").Call(), + ) + fmt.Printf("%#v", f) + // Output: + // package a + // + // import ( + // "C" + // "fmt" + // ) + // + // func init() { + // C.Foo() + // fmt.Print() + // } +} + +func ExampleFile_CgoPreamble_no_preamble_single() { + f := NewFile("a") + f.Func().Id("init").Params().Block( + Qual("C", "Foo").Call(), + ) + fmt.Printf("%#v", f) + // Output: + // package a + // + // import "C" + // + // func init() { + // C.Foo() + // } +} + +func ExampleFile_CgoPreamble_no_preamble_single_anon() { + f := NewFile("a") + f.Anon("C") + f.Func().Id("init").Params().Block() + fmt.Printf("%#v", f) + // Output: + // package a + // + // import "C" + // + // func init() {} +} + +func ExampleFile_CgoPreamble_no_preamble_anon() { + f := NewFile("a") + f.Anon("C") + f.Func().Id("init").Params().Block( + Qual("fmt", "Print").Call(), + ) + fmt.Printf("%#v", f) + // Output: + // package a + // + // import ( + // "C" + // "fmt" + // ) + // + // func init() { + // fmt.Print() + // } +} + +func ExampleOp_complex_conditions() { + c := If(Parens(Id("a").Op("||").Id("b")).Op("&&").Id("c")).Block() + fmt.Printf("%#v", c) + // Output: + // if (a || b) && c { + // } +} + +func ExampleLit_bool_true() { + c := Lit(true) + fmt.Printf("%#v", c) + // Output: + // true +} + +func ExampleLit_bool_false() { + c := Lit(false) + fmt.Printf("%#v", c) + // Output: + // false +} + +func ExampleLit_byte() { + // Lit can't tell the difference between byte and uint8. Use LitByte to + // render byte literals. + c := Lit(byte(0x1)) + fmt.Printf("%#v", c) + // Output: + // uint8(0x1) +} + +func ExampleLit_complex64() { + c := Lit(complex64(0 + 0i)) + fmt.Printf("%#v", c) + // Output: + // complex64(0 + 0i) +} + +func ExampleLit_complex128() { + c := Lit(0 + 0i) + fmt.Printf("%#v", c) + // Output: + // (0 + 0i) +} + +func ExampleLit_float32() { + c := Lit(float32(1)) + fmt.Printf("%#v", c) + // Output: + // float32(1) +} + +func ExampleLit_float64_one_point_zero() { + c := Lit(1.0) + fmt.Printf("%#v", c) + // Output: + // 1.0 +} + +func ExampleLit_float64_zero() { + c := Lit(0.0) + fmt.Printf("%#v", c) + // Output: + // 0.0 +} + +func ExampleLit_float64_negative() { + c := Lit(-0.1) + fmt.Printf("%#v", c) + // Output: + // -0.1 +} + +func ExampleLit_float64_negative_whole() { + c := Lit(-1.0) + fmt.Printf("%#v", c) + // Output: + // -1.0 +} + +func ExampleLit_int() { + c := Lit(1) + fmt.Printf("%#v", c) + // Output: + // 1 +} + +func ExampleLit_int8() { + c := Lit(int8(1)) + fmt.Printf("%#v", c) + // Output: + // int8(1) +} + +func ExampleLit_int16() { + c := Lit(int16(1)) + fmt.Printf("%#v", c) + // Output: + // int16(1) +} + +func ExampleLit_int32() { + c := Lit(int32(1)) + fmt.Printf("%#v", c) + // Output: + // int32(1) +} + +func ExampleLit_int64() { + c := Lit(int64(1)) + fmt.Printf("%#v", c) + // Output: + // int64(1) +} + +func ExampleLit_uint() { + c := Lit(uint(0x1)) + fmt.Printf("%#v", c) + // Output: + // uint(0x1) +} + +func ExampleLit_uint8() { + c := Lit(uint8(0x1)) + fmt.Printf("%#v", c) + // Output: + // uint8(0x1) +} + +func ExampleLit_uint16() { + c := Lit(uint16(0x1)) + fmt.Printf("%#v", c) + // Output: + // uint16(0x1) +} + +func ExampleLit_uint32() { + c := Lit(uint32(0x1)) + fmt.Printf("%#v", c) + // Output: + // uint32(0x1) +} + +func ExampleLit_uint64() { + c := Lit(uint64(0x1)) + fmt.Printf("%#v", c) + // Output: + // uint64(0x1) +} + +func ExampleLit_uintptr() { + c := Lit(uintptr(0x1)) + fmt.Printf("%#v", c) + // Output: + // uintptr(0x1) +} + +func ExampleLit_rune() { + // Lit can't tell the difference between rune and int32. Use LitRune to + // render rune literals. + c := Lit('x') + fmt.Printf("%#v", c) + // Output: + // int32(120) +} + +func ExampleLitRune() { + c := LitRune('x') + fmt.Printf("%#v", c) + // Output: + // 'x' +} + +func ExampleLitRuneFunc() { + c := LitRuneFunc(func() rune { + return '\t' + }) + fmt.Printf("%#v", c) + // Output: + // '\t' +} + +func ExampleLitByte() { + c := LitByte(byte(1)) + fmt.Printf("%#v", c) + // Output: + // byte(0x1) +} + +func ExampleLitByteFunc() { + c := LitByteFunc(func() byte { + return byte(2) + }) + fmt.Printf("%#v", c) + // Output: + // byte(0x2) +} + +func ExampleLit_string() { + c := Lit("foo") + fmt.Printf("%#v", c) + // Output: + // "foo" +} + +func ExampleValues_dict_single() { + c := Map(String()).String().Values(Dict{ + Lit("a"): Lit("b"), + }) + fmt.Printf("%#v", c) + // Output: + // map[string]string{"a": "b"} +} + +func ExampleValues_dict_multiple() { + c := Map(String()).String().Values(Dict{ + Lit("a"): Lit("b"), + Lit("c"): Lit("d"), + }) + fmt.Printf("%#v", c) + // Output: + // map[string]string{ + // "a": "b", + // "c": "d", + // } +} + +func ExampleValues_dict_composite() { + c := Op("&").Id("Person").Values(Dict{ + Id("Age"): Lit(1), + Id("Name"): Lit("a"), + }) + fmt.Printf("%#v", c) + // Output: + // &Person{ + // Age: 1, + // Name: "a", + // } +} + +func ExampleAdd() { + ptr := Op("*") + c := Id("a").Op("=").Add(ptr).Id("b") + fmt.Printf("%#v", c) + // Output: + // a = *b +} + +func ExampleAdd_var() { + a := Id("a") + i := Int() + c := Var().Add(a, i) + fmt.Printf("%#v", c) + // Output: + // var a int +} + +func ExampleAppend() { + c := Append(Id("a"), Id("b")) + fmt.Printf("%#v", c) + // Output: + // append(a, b) +} + +func ExampleAppend_more() { + c := Id("a").Op("=").Append(Id("a"), Id("b").Op("...")) + fmt.Printf("%#v", c) + // Output: + // a = append(a, b...) +} + +func ExampleAssert() { + c := List(Id("b"), Id("ok")).Op(":=").Id("a").Assert(Bool()) + fmt.Printf("%#v", c) + // Output: + // b, ok := a.(bool) +} + +func ExampleBlock() { + c := Func().Id("foo").Params().String().Block( + Id("a").Op("=").Id("b"), + Id("b").Op("++"), + Return(Id("b")), + ) + fmt.Printf("%#v", c) + // Output: + // func foo() string { + // a = b + // b++ + // return b + // } +} + +func ExampleBlock_if() { + c := If(Id("a").Op(">").Lit(10)).Block( + Id("a").Op("=").Id("a").Op("/").Lit(2), + ) + fmt.Printf("%#v", c) + // Output: + // if a > 10 { + // a = a / 2 + // } +} + +func ExampleValuesFunc() { + c := Id("numbers").Op(":=").Index().Int().ValuesFunc(func(g *Group) { + for i := 0; i <= 5; i++ { + g.Lit(i) + } + }) + fmt.Printf("%#v", c) + // Output: + // numbers := []int{0, 1, 2, 3, 4, 5} +} + +func ExampleBlockFunc() { + increment := true + name := "a" + c := Func().Id("a").Params().BlockFunc(func(g *Group) { + g.Id(name).Op("=").Lit(1) + if increment { + g.Id(name).Op("++") + } else { + g.Id(name).Op("--") + } + }) + fmt.Printf("%#v", c) + // Output: + // func a() { + // a = 1 + // a++ + // } +} + +func ExampleBool() { + c := Var().Id("b").Bool() + fmt.Printf("%#v", c) + // Output: + // var b bool +} + +func ExampleBreak() { + c := For( + Id("i").Op(":=").Lit(0), + Id("i").Op("<").Lit(10), + Id("i").Op("++"), + ).Block( + If(Id("i").Op(">").Lit(5)).Block( + Break(), + ), + ) + fmt.Printf("%#v", c) + // Output: + // for i := 0; i < 10; i++ { + // if i > 5 { + // break + // } + // } +} + +func ExampleByte() { + c := Id("b").Op(":=").Id("a").Assert(Byte()) + fmt.Printf("%#v", c) + // Output: + // b := a.(byte) +} + +func ExampleCall() { + c := Qual("fmt", "Printf").Call( + Lit("%#v: %T\n"), + Id("a"), + Id("b"), + ) + fmt.Printf("%#v", c) + // Output: + // fmt.Printf("%#v: %T\n", a, b) +} + +func ExampleCall_fmt() { + c := Id("a").Call(Lit("b")) + fmt.Printf("%#v", c) + // Output: + // a("b") +} + +func ExampleCallFunc() { + f := func(name string, second string) { + c := Id("foo").CallFunc(func(g *Group) { + g.Id(name) + if second != "" { + g.Lit(second) + } + }) + fmt.Printf("%#v\n", c) + } + f("a", "b") + f("c", "") + // Output: + // foo(a, "b") + // foo(c) +} + +func ExampleCap() { + c := Id("i").Op(":=").Cap(Id("v")) + fmt.Printf("%#v", c) + // Output: + // i := cap(v) +} + +func ExampleCase() { + c := Switch(Id("person")).Block( + Case(Id("John"), Id("Peter")).Block( + Return(Lit("male")), + ), + Case(Id("Gill")).Block( + Return(Lit("female")), + ), + ) + fmt.Printf("%#v", c) + // Output: + // switch person { + // case John, Peter: + // return "male" + // case Gill: + // return "female" + // } +} + +func ExampleBlock_case() { + c := Select().Block( + Case(Op("<-").Id("done")).Block( + Return(Nil()), + ), + Case(List(Err(), Id("open")).Op(":=").Op("<-").Id("fail")).Block( + If(Op("!").Id("open")).Block( + Return(Err()), + ), + ), + ) + fmt.Printf("%#v", c) + // Output: + // select { + // case <-done: + // return nil + // case err, open := <-fail: + // if !open { + // return err + // } + // } +} + +func ExampleBlockFunc_case() { + preventExitOnError := true + c := Select().Block( + Case(Op("<-").Id("done")).Block( + Return(Nil()), + ), + Case(Err().Op(":=").Op("<-").Id("fail")).BlockFunc(func(g *Group) { + if !preventExitOnError { + g.Return(Err()) + } else { + g.Qual("fmt", "Println").Call(Err()) + } + }), + ) + fmt.Printf("%#v", c) + // Output: + // select { + // case <-done: + // return nil + // case err := <-fail: + // fmt.Println(err) + // } +} + +func ExampleCaseFunc() { + samIsMale := false + c := Switch(Id("person")).Block( + CaseFunc(func(g *Group) { + g.Id("John") + g.Id("Peter") + if samIsMale { + g.Id("Sam") + } + }).Block( + Return(Lit("male")), + ), + CaseFunc(func(g *Group) { + g.Id("Gill") + if !samIsMale { + g.Id("Sam") + } + }).Block( + Return(Lit("female")), + ), + ) + fmt.Printf("%#v", c) + // Output: + // switch person { + // case John, Peter: + // return "male" + // case Gill, Sam: + // return "female" + // } +} + +func ExampleChan() { + c := Func().Id("init").Params().Block( + Id("c").Op(":=").Make(Chan().Qual("os", "Signal"), Lit(1)), + Qual("os/signal", "Notify").Call(Id("c"), Qual("os", "Interrupt")), + Qual("os/signal", "Notify").Call(Id("c"), Qual("syscall", "SIGTERM")), + Go().Func().Params().Block( + Op("<-").Id("c"), + Id("cancel").Call(), + ).Call(), + ) + fmt.Printf("%#v", c) + // Output: + // func init() { + // c := make(chan os.Signal, 1) + // signal.Notify(c, os.Interrupt) + // signal.Notify(c, syscall.SIGTERM) + // go func() { + // <-c + // cancel() + // }() + // } +} + +func ExampleClose() { + c := Block( + Id("ch").Op(":=").Make(Chan().Struct()), + Go().Func().Params().Block( + Op("<-").Id("ch"), + Qual("fmt", "Println").Call(Lit("done.")), + ).Call(), + Close(Id("ch")), + ) + fmt.Printf("%#v", c) + // Output: + // { + // ch := make(chan struct{}) + // go func() { + // <-ch + // fmt.Println("done.") + // }() + // close(ch) + // } +} + +func ExampleComment() { + f := NewFile("a") + f.Comment("Foo returns the string \"foo\"") + f.Func().Id("Foo").Params().String().Block( + Return(Lit("foo")).Comment("return the string foo"), + ) + fmt.Printf("%#v", f) + // Output: + // package a + // + // // Foo returns the string "foo" + // func Foo() string { + // return "foo" // return the string foo + // } +} + +func ExampleComment_multiline() { + c := Comment("a\nb") + fmt.Printf("%#v", c) + // Output: + // /* + // a + // b + // */ +} + +func ExampleComment_formatting_disabled() { + c := Id("foo").Call(Comment("/* inline */")).Comment("//no-space") + fmt.Printf("%#v", c) + // Output: + // foo( /* inline */ ) //no-space +} + +func ExampleCommentf() { + name := "foo" + val := "bar" + c := Id(name).Op(":=").Lit(val).Commentf("%s is the string \"%s\"", name, val) + fmt.Printf("%#v", c) + // Output: + // foo := "bar" // foo is the string "bar" +} + +func ExampleComplex() { + c := Func().Id("main").Params().Block( + Id("c1").Op(":=").Lit(1+3.75i), + Id("c2").Op(":=").Complex(Lit(1), Lit(3.75)), + Qual("fmt", "Println").Call(Id("c1").Op("==").Id("c2")), + ) + fmt.Printf("%#v", c) + // Output: + // func main() { + // c1 := (1 + 3.75i) + // c2 := complex(1, 3.75) + // fmt.Println(c1 == c2) + // } +} + +func ExampleComplex128() { + c := Func().Id("main").Params().Block( + Var().Id("c").Complex128(), + Id("c").Op("=").Lit(1+2i), + Qual("fmt", "Println").Call(Id("c")), + ) + fmt.Printf("%#v", c) + // Output: + // func main() { + // var c complex128 + // c = (1 + 2i) + // fmt.Println(c) + // } +} + +func ExampleComplex64() { + c := Func().Id("main").Params().Block( + Var().Id("c64").Complex64(), + Id("c64").Op("=").Complex(Lit(5), Float32().Parens(Lit(2))), + Qual("fmt", "Printf").Call(Lit("%T\n"), Id("c64")), + ) + fmt.Printf("%#v", c) + // Output: + // func main() { + // var c64 complex64 + // c64 = complex(5, float32(2)) + // fmt.Printf("%T\n", c64) + // } +} + +func ExampleParams() { + c := Func().Params( + Id("a").Id("A"), + ).Id("foo").Params( + Id("b"), + Id("c").String(), + ).String().Block( + Return(Id("b").Op("+").Id("c")), + ) + fmt.Printf("%#v", c) + // Output: + // func (a A) foo(b, c string) string { + // return b + c + // } +} + +func ExampleIndex() { + c := Var().Id("a").Index().String() + fmt.Printf("%#v", c) + // Output: + // var a []string +} + +func ExampleIndex_index() { + c := Id("a").Op(":=").Id("b").Index(Lit(0), Lit(1)) + fmt.Printf("%#v", c) + // Output: + // a := b[0:1] +} + +func ExampleIndex_empty() { + c := Id("a").Op(":=").Id("b").Index(Lit(1), Empty()) + fmt.Printf("%#v", c) + // Output: + // a := b[1:] +} + +func ExampleOp() { + c := Id("a").Op(":=").Id("b").Call() + fmt.Printf("%#v", c) + // Output: + // a := b() +} + +func ExampleOp_star() { + c := Id("a").Op("=").Op("*").Id("b") + fmt.Printf("%#v", c) + // Output: + // a = *b +} + +func ExampleOp_variadic() { + c := Id("a").Call(Id("b").Op("...")) + fmt.Printf("%#v", c) + // Output: + // a(b...) +} + +func ExampleNewFilePath() { + f := NewFilePath("a.b/c") + f.Func().Id("init").Params().Block( + Qual("a.b/c", "Foo").Call().Comment("Local package - alias is omitted."), + Qual("d.e/f", "Bar").Call().Comment("Import is automatically added."), + Qual("g.h/f", "Baz").Call().Comment("Colliding package name is automatically renamed."), + ) + fmt.Printf("%#v", f) + // Output: + // package c + // + // import ( + // f "d.e/f" + // f1 "g.h/f" + // ) + // + // func init() { + // Foo() // Local package - alias is omitted. + // f.Bar() // Import is automatically added. + // f1.Baz() // Colliding package name is automatically renamed. + // } +} + +func ExampleStruct_empty() { + c := Id("c").Op(":=").Make(Chan().Struct()) + fmt.Printf("%#v", c) + // Output: + // c := make(chan struct{}) +} + +func ExampleStruct() { + c := Type().Id("foo").Struct( + List(Id("x"), Id("y")).Int(), + Id("u").Float32(), + ) + fmt.Printf("%#v", c) + // Output: + // type foo struct { + // x, y int + // u float32 + // } +} + +func ExampleDefer() { + c := Defer().Id("foo").Call() + fmt.Printf("%#v", c) + // Output: + // defer foo() +} + +func ExampleGoto() { + c := Goto().Id("Outer") + fmt.Printf("%#v", c) + // Output: + // goto Outer +} + +func ExampleStatement_Clone_broken() { + a := Id("a") + c := Block( + a.Call(), + a.Call(), + ) + fmt.Printf("%#v", c) + // Output: + // { + // a()() + // a()() + // } +} + +func ExampleStatement_Clone_fixed() { + a := Id("a") + c := Block( + a.Clone().Call(), + a.Clone().Call(), + ) + fmt.Printf("%#v", c) + // Output: + // { + // a() + // a() + // } +} + +func ExampleFile_Render() { + f := NewFile("a") + f.Func().Id("main").Params().Block() + buf := &bytes.Buffer{} + err := f.Render(buf) + if err != nil { + fmt.Println(err.Error()) + } else { + fmt.Println(buf.String()) + } + // Output: + // package a + // + // func main() {} +} + +func ExampleLit() { + c := Id("a").Op(":=").Lit("a") + fmt.Printf("%#v", c) + // Output: + // a := "a" +} + +func ExampleLit_float() { + c := Id("a").Op(":=").Lit(1.5) + fmt.Printf("%#v", c) + // Output: + // a := 1.5 +} + +func ExampleLitFunc() { + c := Id("a").Op(":=").LitFunc(func() interface{} { return 1 + 1 }) + fmt.Printf("%#v", c) + // Output: + // a := 2 +} + +func ExampleDot() { + c := Qual("a.b/c", "Foo").Call().Dot("Bar").Index(Lit(0)).Dot("Baz") + fmt.Printf("%#v", c) + // Output: + // c.Foo().Bar[0].Baz +} + +func ExampleList() { + c := List(Id("a"), Err()).Op(":=").Id("b").Call() + fmt.Printf("%#v", c) + // Output: + // a, err := b() +} + +func ExampleQual() { + c := Qual("encoding/gob", "NewEncoder").Call() + fmt.Printf("%#v", c) + // Output: + // gob.NewEncoder() +} + +func ExampleQual_file() { + f := NewFilePath("a.b/c") + f.Func().Id("init").Params().Block( + Qual("a.b/c", "Foo").Call().Comment("Local package - name is omitted."), + Qual("d.e/f", "Bar").Call().Comment("Import is automatically added."), + Qual("g.h/f", "Baz").Call().Comment("Colliding package name is renamed."), + ) + fmt.Printf("%#v", f) + // Output: + // package c + // + // import ( + // f "d.e/f" + // f1 "g.h/f" + // ) + // + // func init() { + // Foo() // Local package - name is omitted. + // f.Bar() // Import is automatically added. + // f1.Baz() // Colliding package name is renamed. + // } +} + +func ExampleQual_local() { + f := NewFilePath("a.b/c") + f.Func().Id("main").Params().Block( + Qual("a.b/c", "D").Call(), + ) + fmt.Printf("%#v", f) + // Output: + // package c + // + // func main() { + // D() + // } +} + +func ExampleId() { + c := If(Id("i").Op("==").Id("j")).Block( + Return(Id("i")), + ) + fmt.Printf("%#v", c) + // Output: + // if i == j { + // return i + // } +} + +func ExampleErr() { + c := If( + Err().Op(":=").Id("foo").Call(), + Err().Op("!=").Nil(), + ).Block( + Return(Err()), + ) + fmt.Printf("%#v", c) + // Output: + // if err := foo(); err != nil { + // return err + // } +} + +func ExampleSwitch() { + c := Switch(Id("value").Dot("Kind").Call()).Block( + Case(Qual("reflect", "Float32"), Qual("reflect", "Float64")).Block( + Return(Lit("float")), + ), + Case(Qual("reflect", "Bool")).Block( + Return(Lit("bool")), + ), + Case(Qual("reflect", "Uintptr")).Block( + Fallthrough(), + ), + Default().Block( + Return(Lit("none")), + ), + ) + fmt.Printf("%#v", c) + // Output: + // switch value.Kind() { + // case reflect.Float32, reflect.Float64: + // return "float" + // case reflect.Bool: + // return "bool" + // case reflect.Uintptr: + // fallthrough + // default: + // return "none" + // } +} + +func ExampleTag() { + c := Type().Id("foo").Struct( + Id("A").String().Tag(map[string]string{"json": "a"}), + Id("B").Int().Tag(map[string]string{"json": "b", "bar": "baz"}), + ) + fmt.Printf("%#v", c) + // Output: + // type foo struct { + // A string `json:"a"` + // B int `bar:"baz" json:"b"` + // } +} + +func ExampleNull_and_nil() { + c := Func().Id("foo").Params( + nil, + Id("s").String(), + Null(), + Id("i").Int(), + ).Block() + fmt.Printf("%#v", c) + // Output: + // func foo(s string, i int) {} +} + +func ExampleNull_index() { + c := Id("a").Op(":=").Id("b").Index(Lit(1), Null()) + fmt.Printf("%#v", c) + // Output: + // a := b[1] +} + +func ExampleEmpty() { + c := Id("a").Op(":=").Id("b").Index(Lit(1), Empty()) + fmt.Printf("%#v", c) + // Output: + // a := b[1:] +} + +func ExampleBlock_complex() { + collection := func(name string, key Code, value Code) *Statement { + if key == nil { + // slice + return Var().Id(name).Index().Add(value) + } else { + // map + return Var().Id(name).Map(key).Add(value) + } + } + c := Func().Id("main").Params().Block( + collection("foo", nil, String()), + collection("bar", String(), Int()), + ) + fmt.Printf("%#v", c) + // Output: + // func main() { + // var foo []string + // var bar map[string]int + // } +} + +func ExampleFunc_declaration() { + c := Func().Id("a").Params().Block() + fmt.Printf("%#v", c) + // Output: + // func a() {} +} + +func ExampleFunc_literal() { + c := Id("a").Op(":=").Func().Params().Block() + fmt.Printf("%#v", c) + // Output: + // a := func() {} +} + +func ExampleInterface() { + c := Type().Id("a").Interface( + Id("b").Params().String(), + ) + fmt.Printf("%#v", c) + // Output: + // type a interface { + // b() string + // } +} + +func ExampleInterface_empty() { + c := Var().Id("a").Interface() + fmt.Printf("%#v", c) + // Output: + // var a interface{} +} + +func ExampleParens() { + c := Id("b").Op(":=").Index().Byte().Parens(Id("s")) + fmt.Printf("%#v", c) + // Output: + // b := []byte(s) +} + +func ExampleParens_order() { + c := Id("a").Op("/").Parens(Id("b").Op("+").Id("c")) + fmt.Printf("%#v", c) + // Output: + // a / (b + c) +} + +func ExampleValues() { + c := Index().String().Values(Lit("a"), Lit("b")) + fmt.Printf("%#v", c) + // Output: + // []string{"a", "b"} +} + +func ExampleDo() { + f := func(name string, isMap bool) *Statement { + return Id(name).Op(":=").Do(func(s *Statement) { + if isMap { + s.Map(String()).String() + } else { + s.Index().String() + } + }).Values() + } + fmt.Printf("%#v\n%#v", f("a", true), f("b", false)) + // Output: + // a := map[string]string{} + // b := []string{} +} + +func ExampleReturn() { + c := Return(Id("a"), Id("b")) + fmt.Printf("%#v", c) + // Output: + // return a, b +} + +func ExampleMap() { + c := Id("a").Op(":=").Map(String()).String().Values() + fmt.Printf("%#v", c) + // Output: + // a := map[string]string{} +} + +func ExampleDict() { + c := Id("a").Op(":=").Map(String()).String().Values(Dict{ + Lit("a"): Lit("b"), + Lit("c"): Lit("d"), + }) + fmt.Printf("%#v", c) + // Output: + // a := map[string]string{ + // "a": "b", + // "c": "d", + // } +} + +func ExampleDict_nil() { + c := Id("a").Op(":=").Map(String()).String().Values() + fmt.Printf("%#v", c) + // Output: + // a := map[string]string{} +} + +func ExampleDictFunc() { + c := Id("a").Op(":=").Map(String()).String().Values(DictFunc(func(d Dict) { + d[Lit("a")] = Lit("b") + d[Lit("c")] = Lit("d") + })) + fmt.Printf("%#v", c) + // Output: + // a := map[string]string{ + // "a": "b", + // "c": "d", + // } +} + +func ExampleDefs() { + c := Const().Defs( + Id("a").Op("=").Lit("a"), + Id("b").Op("=").Lit("b"), + ) + fmt.Printf("%#v", c) + // Output: + // const ( + // a = "a" + // b = "b" + // ) +} + +func ExampleIf() { + c := If( + Err().Op(":=").Id("a").Call(), + Err().Op("!=").Nil(), + ).Block( + Return(Err()), + ) + fmt.Printf("%#v", c) + // Output: + // if err := a(); err != nil { + // return err + // } +} + +func ExampleId_local() { + c := Id("a").Op(":=").Lit(1) + fmt.Printf("%#v", c) + // Output: + // a := 1 +} + +func ExampleId_select() { + c := Id("a").Dot("b").Dot("c").Call() + fmt.Printf("%#v", c) + // Output: + // a.b.c() +} + +func ExampleId_remote() { + f := NewFile("main") + f.Func().Id("main").Params().Block( + Qual("fmt", "Println").Call( + Lit("Hello, world"), + ), + ) + fmt.Printf("%#v", f) + // Output: + // package main + // + // import "fmt" + // + // func main() { + // fmt.Println("Hello, world") + // } +} + +func ExampleFor() { + c := For( + Id("i").Op(":=").Lit(0), + Id("i").Op("<").Lit(10), + Id("i").Op("++"), + ).Block( + Qual("fmt", "Println").Call(Id("i")), + ) + fmt.Printf("%#v", c) + // Output: + // for i := 0; i < 10; i++ { + // fmt.Println(i) + // } +} + +func ExampleNewFile() { + f := NewFile("main") + f.Func().Id("main").Params().Block( + Qual("fmt", "Println").Call(Lit("Hello, world")), + ) + fmt.Printf("%#v", f) + // Output: + // package main + // + // import "fmt" + // + // func main() { + // fmt.Println("Hello, world") + // } +} + +func ExampleNewFilePathName() { + f := NewFilePathName("a.b/c", "main") + f.Func().Id("main").Params().Block( + Qual("a.b/c", "Foo").Call(), + ) + fmt.Printf("%#v", f) + // Output: + // package main + // + // func main() { + // Foo() + // } +} + +func ExampleFile_HeaderAndPackageComments() { + f := NewFile("c") + f.CanonicalPath = "d.e/f" + f.HeaderComment("Code generated by...") + f.PackageComment("Package c implements...") + f.Func().Id("init").Params().Block() + fmt.Printf("%#v", f) + // Output: + // // Code generated by... + // + // // Package c implements... + // package c // import "d.e/f" + // + // func init() {} +} + +func ExampleFile_Anon() { + f := NewFile("c") + f.Anon("a") + f.Func().Id("init").Params().Block() + fmt.Printf("%#v", f) + // Output: + // package c + // + // import _ "a" + // + // func init() {} +} + +func ExampleFile_PackagePrefix() { + f := NewFile("a") + f.PackagePrefix = "pkg" + f.Func().Id("main").Params().Block( + Qual("b.c/d", "E").Call(), + ) + fmt.Printf("%#v", f) + // Output: + // package a + // + // import pkg_d "b.c/d" + // + // func main() { + // pkg_d.E() + // } +} diff --git a/vendor/github.com/dave/jennifer/jen/file.go b/vendor/github.com/dave/jennifer/jen/file.go new file mode 100644 index 00000000..1ce442b9 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/file.go @@ -0,0 +1,262 @@ +package jen + +import ( + "bytes" + "fmt" + "regexp" + "strings" +) + +// NewFile Creates a new file, with the specified package name. +func NewFile(packageName string) *File { + return &File{ + Group: &Group{ + multi: true, + }, + name: packageName, + imports: map[string]importdef{}, + hints: map[string]importdef{}, + } +} + +// NewFilePath creates a new file while specifying the package path - the +// package name is inferred from the path. +func NewFilePath(packagePath string) *File { + return &File{ + Group: &Group{ + multi: true, + }, + name: guessAlias(packagePath), + path: packagePath, + imports: map[string]importdef{}, + hints: map[string]importdef{}, + } +} + +// NewFilePathName creates a new file with the specified package path and name. +func NewFilePathName(packagePath, packageName string) *File { + return &File{ + Group: &Group{ + multi: true, + }, + name: packageName, + path: packagePath, + imports: map[string]importdef{}, + hints: map[string]importdef{}, + } +} + +// File represents a single source file. Package imports are managed +// automaticaly by File. +type File struct { + *Group + name string + path string + imports map[string]importdef + hints map[string]importdef + comments []string + headers []string + cgoPreamble []string + // If you're worried about generated package aliases conflicting with local variable names, you + // can set a prefix here. Package foo becomes {prefix}_foo. + PackagePrefix string + // CanonicalPath adds a canonical import path annotation to the package clause. + CanonicalPath string +} + +// importdef is used to differentiate packages where we know the package name from packages where the +// import is aliased. If alias == false, then name is the actual package name, and the import will be +// rendered without an alias. If used == false, the import has not been used in code yet and should be +// excluded from the import block. +type importdef struct { + name string + alias bool +} + +// HeaderComment adds a comment to the top of the file, above any package +// comments. A blank line is rendered below the header comments, ensuring +// header comments are not included in the package doc. +func (f *File) HeaderComment(comment string) { + f.headers = append(f.headers, comment) +} + +// PackageComment adds a comment to the top of the file, above the package +// keyword. +func (f *File) PackageComment(comment string) { + f.comments = append(f.comments, comment) +} + +// CgoPreamble adds a cgo preamble comment that is rendered directly before the "C" pseudo-package +// import. +func (f *File) CgoPreamble(comment string) { + f.cgoPreamble = append(f.cgoPreamble, comment) +} + +// Anon adds an anonymous import. +func (f *File) Anon(paths ...string) { + for _, p := range paths { + f.imports[p] = importdef{name: "_", alias: true} + } +} + +// ImportName provides the package name for a path. If specified, the alias will be omitted from the +// import block. This is optional. If not specified, a sensible package name is used based on the path +// and this is added as an alias in the import block. +func (f *File) ImportName(path, name string) { + f.hints[path] = importdef{name: name, alias: false} +} + +// ImportNames allows multiple names to be imported as a map. Use the [gennames](gennames) command to +// automatically generate a go file containing a map of a selection of package names. +func (f *File) ImportNames(names map[string]string) { + for path, name := range names { + f.hints[path] = importdef{name: name, alias: false} + } +} + +// ImportAlias provides the alias for a package path that should be used in the import block. A +// period can be used to force a dot-import. +func (f *File) ImportAlias(path, alias string) { + f.hints[path] = importdef{name: alias, alias: true} +} + +func (f *File) isLocal(path string) bool { + return f.path == path +} + +var reserved = []string{ + /* keywords */ + "break", "default", "func", "interface", "select", "case", "defer", "go", "map", "struct", "chan", "else", "goto", "package", "switch", "const", "fallthrough", "if", "range", "type", "continue", "for", "import", "return", "var", + /* predeclared */ + "bool", "byte", "complex64", "complex128", "error", "float32", "float64", "int", "int8", "int16", "int32", "int64", "rune", "string", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "true", "false", "iota", "nil", "append", "cap", "close", "complex", "copy", "delete", "imag", "len", "make", "new", "panic", "print", "println", "real", "recover", + /* common variables */ + "err", +} + +func isReservedWord(alias string) bool { + for _, name := range reserved { + if alias == name { + return true + } + } + return false +} + +func (f *File) isValidAlias(alias string) bool { + // multiple dot-imports are ok + if alias == "." { + return true + } + // the import alias is invalid if it's a reserved word + if isReservedWord(alias) { + return false + } + // the import alias is invalid if it's already been registered + for _, v := range f.imports { + if alias == v.name { + return false + } + } + return true +} + +func (f *File) isDotImport(path string) bool { + if id, ok := f.hints[path]; ok { + return id.name == "." && id.alias + } + return false +} + +func (f *File) register(path string) string { + if f.isLocal(path) { + // notest + // should never get here becasue in Qual the packageToken will be null, + // so render will never be called. + return "" + } + + // if the path has been registered previously, simply return the name + def := f.imports[path] + if def.name != "" && def.name != "_" { + return def.name + } + + // special case for "C" pseudo-package + if path == "C" { + f.imports["C"] = importdef{name: "C", alias: false} + return "C" + } + + var name string + var alias bool + + if hint := f.hints[path]; hint.name != "" { + // look up the path in the list of provided package names and aliases by ImportName / ImportAlias + name = hint.name + alias = hint.alias + } else if standardLibraryHints[path] != "" { + // look up the path in the list of standard library packages + name = standardLibraryHints[path] + alias = false + } else { + // if a hint is not found for the package, guess the alias from the package path + name = guessAlias(path) + alias = true + } + + // If the name is invalid or has been registered already, make it unique by appending a number + unique := name + i := 0 + for !f.isValidAlias(unique) { + i++ + unique = fmt.Sprintf("%s%d", name, i) + } + + // If we've changed the name to make it unique, it should definitely be an alias + if unique != name { + alias = true + } + + // Only add a prefix if the name is an alias + if f.PackagePrefix != "" && alias { + unique = f.PackagePrefix + "_" + unique + } + + // Register the eventual name + f.imports[path] = importdef{name: unique, alias: alias} + + return unique +} + +// GoString renders the File for testing. Any error will cause a panic. +func (f *File) GoString() string { + buf := &bytes.Buffer{} + if err := f.Render(buf); err != nil { + panic(err) + } + return buf.String() +} + +func guessAlias(path string) string { + alias := path + + if strings.HasSuffix(alias, "/") { + // training slashes are usually tolerated, so we can get rid of one if + // it exists + alias = alias[:len(alias)-1] + } + + if strings.Contains(alias, "/") { + // if the path contains a "/", use the last part + alias = alias[strings.LastIndex(alias, "/")+1:] + } + + // alias should be lower case + alias = strings.ToLower(alias) + + // alias should now only contain alphanumerics + importsRegex := regexp.MustCompile(`[^a-z0-9]`) + alias = importsRegex.ReplaceAllString(alias, "") + + return alias +} diff --git a/vendor/github.com/dave/jennifer/jen/file_test.go b/vendor/github.com/dave/jennifer/jen/file_test.go new file mode 100644 index 00000000..798faf63 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/file_test.go @@ -0,0 +1,48 @@ +package jen + +import ( + "fmt" + "testing" +) + +func TestGuessAlias(t *testing.T) { + + data := map[string]string{ + "A": "a", + "a": "a", + "a$": "a", + "a/b": "b", + "a/b/c": "c", + "a/b/c-d": "cd", + "a/b/c-d/": "cd", + "a.b": "ab", + "a/b.c": "bc", + "a/b-c.d": "bcd", + "a/bb-ccc.dddd": "bbcccdddd", + "a/foo-go": "foogo", + } + for path, expected := range data { + if guessAlias(path) != expected { + fmt.Printf("guessAlias test failed %s should return %s but got %s\n", path, expected, guessAlias(path)) + t.Fail() + } + } +} + +func TestValidAlias(t *testing.T) { + data := map[string]bool{ + "a": true, // ok + "b": false, // already registered + "go": false, // keyword + "int": false, // predeclared + "err": false, // common name + } + f := NewFile("test") + f.register("b") + for alias, expected := range data { + if f.isValidAlias(alias) != expected { + fmt.Printf("isValidAlias test failed %s should return %t but got %t\n", alias, expected, f.isValidAlias(alias)) + t.Fail() + } + } +} diff --git a/vendor/github.com/dave/jennifer/jen/generated.go b/vendor/github.com/dave/jennifer/jen/generated.go new file mode 100644 index 00000000..3983cf97 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/generated.go @@ -0,0 +1,2274 @@ +// This file is generated - do not edit. + +package jen + +// Parens renders a single item in parenthesis. Use for type conversion or to specify evaluation order. +func Parens(item Code) *Statement { + return newStatement().Parens(item) +} + +// Parens renders a single item in parenthesis. Use for type conversion or to specify evaluation order. +func (g *Group) Parens(item Code) *Statement { + s := Parens(item) + g.items = append(g.items, s) + return s +} + +// Parens renders a single item in parenthesis. Use for type conversion or to specify evaluation order. +func (s *Statement) Parens(item Code) *Statement { + g := &Group{ + close: ")", + items: []Code{item}, + multi: false, + name: "parens", + open: "(", + separator: "", + } + *s = append(*s, g) + return s +} + +// List renders a comma separated list. Use for multiple return functions. +func List(items ...Code) *Statement { + return newStatement().List(items...) +} + +// List renders a comma separated list. Use for multiple return functions. +func (g *Group) List(items ...Code) *Statement { + s := List(items...) + g.items = append(g.items, s) + return s +} + +// List renders a comma separated list. Use for multiple return functions. +func (s *Statement) List(items ...Code) *Statement { + g := &Group{ + close: "", + items: items, + multi: false, + name: "list", + open: "", + separator: ",", + } + *s = append(*s, g) + return s +} + +// ListFunc renders a comma separated list. Use for multiple return functions. +func ListFunc(f func(*Group)) *Statement { + return newStatement().ListFunc(f) +} + +// ListFunc renders a comma separated list. Use for multiple return functions. +func (g *Group) ListFunc(f func(*Group)) *Statement { + s := ListFunc(f) + g.items = append(g.items, s) + return s +} + +// ListFunc renders a comma separated list. Use for multiple return functions. +func (s *Statement) ListFunc(f func(*Group)) *Statement { + g := &Group{ + close: "", + multi: false, + name: "list", + open: "", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Values renders a comma separated list enclosed by curly braces. Use for slice or composite literals. +func Values(values ...Code) *Statement { + return newStatement().Values(values...) +} + +// Values renders a comma separated list enclosed by curly braces. Use for slice or composite literals. +func (g *Group) Values(values ...Code) *Statement { + s := Values(values...) + g.items = append(g.items, s) + return s +} + +// Values renders a comma separated list enclosed by curly braces. Use for slice or composite literals. +func (s *Statement) Values(values ...Code) *Statement { + g := &Group{ + close: "}", + items: values, + multi: false, + name: "values", + open: "{", + separator: ",", + } + *s = append(*s, g) + return s +} + +// ValuesFunc renders a comma separated list enclosed by curly braces. Use for slice or composite literals. +func ValuesFunc(f func(*Group)) *Statement { + return newStatement().ValuesFunc(f) +} + +// ValuesFunc renders a comma separated list enclosed by curly braces. Use for slice or composite literals. +func (g *Group) ValuesFunc(f func(*Group)) *Statement { + s := ValuesFunc(f) + g.items = append(g.items, s) + return s +} + +// ValuesFunc renders a comma separated list enclosed by curly braces. Use for slice or composite literals. +func (s *Statement) ValuesFunc(f func(*Group)) *Statement { + g := &Group{ + close: "}", + multi: false, + name: "values", + open: "{", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Index renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. +func Index(items ...Code) *Statement { + return newStatement().Index(items...) +} + +// Index renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. +func (g *Group) Index(items ...Code) *Statement { + s := Index(items...) + g.items = append(g.items, s) + return s +} + +// Index renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. +func (s *Statement) Index(items ...Code) *Statement { + g := &Group{ + close: "]", + items: items, + multi: false, + name: "index", + open: "[", + separator: ":", + } + *s = append(*s, g) + return s +} + +// IndexFunc renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. +func IndexFunc(f func(*Group)) *Statement { + return newStatement().IndexFunc(f) +} + +// IndexFunc renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. +func (g *Group) IndexFunc(f func(*Group)) *Statement { + s := IndexFunc(f) + g.items = append(g.items, s) + return s +} + +// IndexFunc renders a colon separated list enclosed by square brackets. Use for array / slice indexes and definitions. +func (s *Statement) IndexFunc(f func(*Group)) *Statement { + g := &Group{ + close: "]", + multi: false, + name: "index", + open: "[", + separator: ":", + } + f(g) + *s = append(*s, g) + return s +} + +// Block renders a statement list enclosed by curly braces. Use for code blocks. A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. +func Block(statements ...Code) *Statement { + return newStatement().Block(statements...) +} + +// Block renders a statement list enclosed by curly braces. Use for code blocks. A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. +func (g *Group) Block(statements ...Code) *Statement { + s := Block(statements...) + g.items = append(g.items, s) + return s +} + +// Block renders a statement list enclosed by curly braces. Use for code blocks. A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. +func (s *Statement) Block(statements ...Code) *Statement { + g := &Group{ + close: "}", + items: statements, + multi: true, + name: "block", + open: "{", + separator: "", + } + *s = append(*s, g) + return s +} + +// BlockFunc renders a statement list enclosed by curly braces. Use for code blocks. A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. +func BlockFunc(f func(*Group)) *Statement { + return newStatement().BlockFunc(f) +} + +// BlockFunc renders a statement list enclosed by curly braces. Use for code blocks. A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. +func (g *Group) BlockFunc(f func(*Group)) *Statement { + s := BlockFunc(f) + g.items = append(g.items, s) + return s +} + +// BlockFunc renders a statement list enclosed by curly braces. Use for code blocks. A special case applies when used directly after Case or Default, where the braces are omitted. This allows use in switch and select statements. +func (s *Statement) BlockFunc(f func(*Group)) *Statement { + g := &Group{ + close: "}", + multi: true, + name: "block", + open: "{", + separator: "", + } + f(g) + *s = append(*s, g) + return s +} + +// Defs renders a statement list enclosed in parenthesis. Use for definition lists. +func Defs(definitions ...Code) *Statement { + return newStatement().Defs(definitions...) +} + +// Defs renders a statement list enclosed in parenthesis. Use for definition lists. +func (g *Group) Defs(definitions ...Code) *Statement { + s := Defs(definitions...) + g.items = append(g.items, s) + return s +} + +// Defs renders a statement list enclosed in parenthesis. Use for definition lists. +func (s *Statement) Defs(definitions ...Code) *Statement { + g := &Group{ + close: ")", + items: definitions, + multi: true, + name: "defs", + open: "(", + separator: "", + } + *s = append(*s, g) + return s +} + +// DefsFunc renders a statement list enclosed in parenthesis. Use for definition lists. +func DefsFunc(f func(*Group)) *Statement { + return newStatement().DefsFunc(f) +} + +// DefsFunc renders a statement list enclosed in parenthesis. Use for definition lists. +func (g *Group) DefsFunc(f func(*Group)) *Statement { + s := DefsFunc(f) + g.items = append(g.items, s) + return s +} + +// DefsFunc renders a statement list enclosed in parenthesis. Use for definition lists. +func (s *Statement) DefsFunc(f func(*Group)) *Statement { + g := &Group{ + close: ")", + multi: true, + name: "defs", + open: "(", + separator: "", + } + f(g) + *s = append(*s, g) + return s +} + +// Call renders a comma separated list enclosed by parenthesis. Use for function calls. +func Call(params ...Code) *Statement { + return newStatement().Call(params...) +} + +// Call renders a comma separated list enclosed by parenthesis. Use for function calls. +func (g *Group) Call(params ...Code) *Statement { + s := Call(params...) + g.items = append(g.items, s) + return s +} + +// Call renders a comma separated list enclosed by parenthesis. Use for function calls. +func (s *Statement) Call(params ...Code) *Statement { + g := &Group{ + close: ")", + items: params, + multi: false, + name: "call", + open: "(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// CallFunc renders a comma separated list enclosed by parenthesis. Use for function calls. +func CallFunc(f func(*Group)) *Statement { + return newStatement().CallFunc(f) +} + +// CallFunc renders a comma separated list enclosed by parenthesis. Use for function calls. +func (g *Group) CallFunc(f func(*Group)) *Statement { + s := CallFunc(f) + g.items = append(g.items, s) + return s +} + +// CallFunc renders a comma separated list enclosed by parenthesis. Use for function calls. +func (s *Statement) CallFunc(f func(*Group)) *Statement { + g := &Group{ + close: ")", + multi: false, + name: "call", + open: "(", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Params renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. +func Params(params ...Code) *Statement { + return newStatement().Params(params...) +} + +// Params renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. +func (g *Group) Params(params ...Code) *Statement { + s := Params(params...) + g.items = append(g.items, s) + return s +} + +// Params renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. +func (s *Statement) Params(params ...Code) *Statement { + g := &Group{ + close: ")", + items: params, + multi: false, + name: "params", + open: "(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// ParamsFunc renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. +func ParamsFunc(f func(*Group)) *Statement { + return newStatement().ParamsFunc(f) +} + +// ParamsFunc renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. +func (g *Group) ParamsFunc(f func(*Group)) *Statement { + s := ParamsFunc(f) + g.items = append(g.items, s) + return s +} + +// ParamsFunc renders a comma separated list enclosed by parenthesis. Use for function parameters and method receivers. +func (s *Statement) ParamsFunc(f func(*Group)) *Statement { + g := &Group{ + close: ")", + multi: false, + name: "params", + open: "(", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Assert renders a period followed by a single item enclosed by parenthesis. Use for type assertions. +func Assert(typ Code) *Statement { + return newStatement().Assert(typ) +} + +// Assert renders a period followed by a single item enclosed by parenthesis. Use for type assertions. +func (g *Group) Assert(typ Code) *Statement { + s := Assert(typ) + g.items = append(g.items, s) + return s +} + +// Assert renders a period followed by a single item enclosed by parenthesis. Use for type assertions. +func (s *Statement) Assert(typ Code) *Statement { + g := &Group{ + close: ")", + items: []Code{typ}, + multi: false, + name: "assert", + open: ".(", + separator: "", + } + *s = append(*s, g) + return s +} + +// Map renders the keyword followed by a single item enclosed by square brackets. Use for map definitions. +func Map(typ Code) *Statement { + return newStatement().Map(typ) +} + +// Map renders the keyword followed by a single item enclosed by square brackets. Use for map definitions. +func (g *Group) Map(typ Code) *Statement { + s := Map(typ) + g.items = append(g.items, s) + return s +} + +// Map renders the keyword followed by a single item enclosed by square brackets. Use for map definitions. +func (s *Statement) Map(typ Code) *Statement { + g := &Group{ + close: "]", + items: []Code{typ}, + multi: false, + name: "map", + open: "map[", + separator: "", + } + *s = append(*s, g) + return s +} + +// If renders the keyword followed by a semicolon separated list. +func If(conditions ...Code) *Statement { + return newStatement().If(conditions...) +} + +// If renders the keyword followed by a semicolon separated list. +func (g *Group) If(conditions ...Code) *Statement { + s := If(conditions...) + g.items = append(g.items, s) + return s +} + +// If renders the keyword followed by a semicolon separated list. +func (s *Statement) If(conditions ...Code) *Statement { + g := &Group{ + close: "", + items: conditions, + multi: false, + name: "if", + open: "if ", + separator: ";", + } + *s = append(*s, g) + return s +} + +// IfFunc renders the keyword followed by a semicolon separated list. +func IfFunc(f func(*Group)) *Statement { + return newStatement().IfFunc(f) +} + +// IfFunc renders the keyword followed by a semicolon separated list. +func (g *Group) IfFunc(f func(*Group)) *Statement { + s := IfFunc(f) + g.items = append(g.items, s) + return s +} + +// IfFunc renders the keyword followed by a semicolon separated list. +func (s *Statement) IfFunc(f func(*Group)) *Statement { + g := &Group{ + close: "", + multi: false, + name: "if", + open: "if ", + separator: ";", + } + f(g) + *s = append(*s, g) + return s +} + +// Return renders the keyword followed by a comma separated list. +func Return(results ...Code) *Statement { + return newStatement().Return(results...) +} + +// Return renders the keyword followed by a comma separated list. +func (g *Group) Return(results ...Code) *Statement { + s := Return(results...) + g.items = append(g.items, s) + return s +} + +// Return renders the keyword followed by a comma separated list. +func (s *Statement) Return(results ...Code) *Statement { + g := &Group{ + close: "", + items: results, + multi: false, + name: "return", + open: "return ", + separator: ",", + } + *s = append(*s, g) + return s +} + +// ReturnFunc renders the keyword followed by a comma separated list. +func ReturnFunc(f func(*Group)) *Statement { + return newStatement().ReturnFunc(f) +} + +// ReturnFunc renders the keyword followed by a comma separated list. +func (g *Group) ReturnFunc(f func(*Group)) *Statement { + s := ReturnFunc(f) + g.items = append(g.items, s) + return s +} + +// ReturnFunc renders the keyword followed by a comma separated list. +func (s *Statement) ReturnFunc(f func(*Group)) *Statement { + g := &Group{ + close: "", + multi: false, + name: "return", + open: "return ", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// For renders the keyword followed by a semicolon separated list. +func For(conditions ...Code) *Statement { + return newStatement().For(conditions...) +} + +// For renders the keyword followed by a semicolon separated list. +func (g *Group) For(conditions ...Code) *Statement { + s := For(conditions...) + g.items = append(g.items, s) + return s +} + +// For renders the keyword followed by a semicolon separated list. +func (s *Statement) For(conditions ...Code) *Statement { + g := &Group{ + close: "", + items: conditions, + multi: false, + name: "for", + open: "for ", + separator: ";", + } + *s = append(*s, g) + return s +} + +// ForFunc renders the keyword followed by a semicolon separated list. +func ForFunc(f func(*Group)) *Statement { + return newStatement().ForFunc(f) +} + +// ForFunc renders the keyword followed by a semicolon separated list. +func (g *Group) ForFunc(f func(*Group)) *Statement { + s := ForFunc(f) + g.items = append(g.items, s) + return s +} + +// ForFunc renders the keyword followed by a semicolon separated list. +func (s *Statement) ForFunc(f func(*Group)) *Statement { + g := &Group{ + close: "", + multi: false, + name: "for", + open: "for ", + separator: ";", + } + f(g) + *s = append(*s, g) + return s +} + +// Switch renders the keyword followed by a semicolon separated list. +func Switch(conditions ...Code) *Statement { + return newStatement().Switch(conditions...) +} + +// Switch renders the keyword followed by a semicolon separated list. +func (g *Group) Switch(conditions ...Code) *Statement { + s := Switch(conditions...) + g.items = append(g.items, s) + return s +} + +// Switch renders the keyword followed by a semicolon separated list. +func (s *Statement) Switch(conditions ...Code) *Statement { + g := &Group{ + close: "", + items: conditions, + multi: false, + name: "switch", + open: "switch ", + separator: ";", + } + *s = append(*s, g) + return s +} + +// SwitchFunc renders the keyword followed by a semicolon separated list. +func SwitchFunc(f func(*Group)) *Statement { + return newStatement().SwitchFunc(f) +} + +// SwitchFunc renders the keyword followed by a semicolon separated list. +func (g *Group) SwitchFunc(f func(*Group)) *Statement { + s := SwitchFunc(f) + g.items = append(g.items, s) + return s +} + +// SwitchFunc renders the keyword followed by a semicolon separated list. +func (s *Statement) SwitchFunc(f func(*Group)) *Statement { + g := &Group{ + close: "", + multi: false, + name: "switch", + open: "switch ", + separator: ";", + } + f(g) + *s = append(*s, g) + return s +} + +// Interface renders the keyword followed by a method list enclosed by curly braces. +func Interface(methods ...Code) *Statement { + return newStatement().Interface(methods...) +} + +// Interface renders the keyword followed by a method list enclosed by curly braces. +func (g *Group) Interface(methods ...Code) *Statement { + s := Interface(methods...) + g.items = append(g.items, s) + return s +} + +// Interface renders the keyword followed by a method list enclosed by curly braces. +func (s *Statement) Interface(methods ...Code) *Statement { + g := &Group{ + close: "}", + items: methods, + multi: true, + name: "interface", + open: "interface{", + separator: "", + } + *s = append(*s, g) + return s +} + +// InterfaceFunc renders the keyword followed by a method list enclosed by curly braces. +func InterfaceFunc(f func(*Group)) *Statement { + return newStatement().InterfaceFunc(f) +} + +// InterfaceFunc renders the keyword followed by a method list enclosed by curly braces. +func (g *Group) InterfaceFunc(f func(*Group)) *Statement { + s := InterfaceFunc(f) + g.items = append(g.items, s) + return s +} + +// InterfaceFunc renders the keyword followed by a method list enclosed by curly braces. +func (s *Statement) InterfaceFunc(f func(*Group)) *Statement { + g := &Group{ + close: "}", + multi: true, + name: "interface", + open: "interface{", + separator: "", + } + f(g) + *s = append(*s, g) + return s +} + +// Struct renders the keyword followed by a field list enclosed by curly braces. +func Struct(fields ...Code) *Statement { + return newStatement().Struct(fields...) +} + +// Struct renders the keyword followed by a field list enclosed by curly braces. +func (g *Group) Struct(fields ...Code) *Statement { + s := Struct(fields...) + g.items = append(g.items, s) + return s +} + +// Struct renders the keyword followed by a field list enclosed by curly braces. +func (s *Statement) Struct(fields ...Code) *Statement { + g := &Group{ + close: "}", + items: fields, + multi: true, + name: "struct", + open: "struct{", + separator: "", + } + *s = append(*s, g) + return s +} + +// StructFunc renders the keyword followed by a field list enclosed by curly braces. +func StructFunc(f func(*Group)) *Statement { + return newStatement().StructFunc(f) +} + +// StructFunc renders the keyword followed by a field list enclosed by curly braces. +func (g *Group) StructFunc(f func(*Group)) *Statement { + s := StructFunc(f) + g.items = append(g.items, s) + return s +} + +// StructFunc renders the keyword followed by a field list enclosed by curly braces. +func (s *Statement) StructFunc(f func(*Group)) *Statement { + g := &Group{ + close: "}", + multi: true, + name: "struct", + open: "struct{", + separator: "", + } + f(g) + *s = append(*s, g) + return s +} + +// Case renders the keyword followed by a comma separated list. +func Case(cases ...Code) *Statement { + return newStatement().Case(cases...) +} + +// Case renders the keyword followed by a comma separated list. +func (g *Group) Case(cases ...Code) *Statement { + s := Case(cases...) + g.items = append(g.items, s) + return s +} + +// Case renders the keyword followed by a comma separated list. +func (s *Statement) Case(cases ...Code) *Statement { + g := &Group{ + close: ":", + items: cases, + multi: false, + name: "case", + open: "case ", + separator: ",", + } + *s = append(*s, g) + return s +} + +// CaseFunc renders the keyword followed by a comma separated list. +func CaseFunc(f func(*Group)) *Statement { + return newStatement().CaseFunc(f) +} + +// CaseFunc renders the keyword followed by a comma separated list. +func (g *Group) CaseFunc(f func(*Group)) *Statement { + s := CaseFunc(f) + g.items = append(g.items, s) + return s +} + +// CaseFunc renders the keyword followed by a comma separated list. +func (s *Statement) CaseFunc(f func(*Group)) *Statement { + g := &Group{ + close: ":", + multi: false, + name: "case", + open: "case ", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Append renders the append built-in function. +func Append(args ...Code) *Statement { + return newStatement().Append(args...) +} + +// Append renders the append built-in function. +func (g *Group) Append(args ...Code) *Statement { + s := Append(args...) + g.items = append(g.items, s) + return s +} + +// Append renders the append built-in function. +func (s *Statement) Append(args ...Code) *Statement { + g := &Group{ + close: ")", + items: args, + multi: false, + name: "append", + open: "append(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// AppendFunc renders the append built-in function. +func AppendFunc(f func(*Group)) *Statement { + return newStatement().AppendFunc(f) +} + +// AppendFunc renders the append built-in function. +func (g *Group) AppendFunc(f func(*Group)) *Statement { + s := AppendFunc(f) + g.items = append(g.items, s) + return s +} + +// AppendFunc renders the append built-in function. +func (s *Statement) AppendFunc(f func(*Group)) *Statement { + g := &Group{ + close: ")", + multi: false, + name: "append", + open: "append(", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Cap renders the cap built-in function. +func Cap(v Code) *Statement { + return newStatement().Cap(v) +} + +// Cap renders the cap built-in function. +func (g *Group) Cap(v Code) *Statement { + s := Cap(v) + g.items = append(g.items, s) + return s +} + +// Cap renders the cap built-in function. +func (s *Statement) Cap(v Code) *Statement { + g := &Group{ + close: ")", + items: []Code{v}, + multi: false, + name: "cap", + open: "cap(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Close renders the close built-in function. +func Close(c Code) *Statement { + return newStatement().Close(c) +} + +// Close renders the close built-in function. +func (g *Group) Close(c Code) *Statement { + s := Close(c) + g.items = append(g.items, s) + return s +} + +// Close renders the close built-in function. +func (s *Statement) Close(c Code) *Statement { + g := &Group{ + close: ")", + items: []Code{c}, + multi: false, + name: "close", + open: "close(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Complex renders the complex built-in function. +func Complex(r Code, i Code) *Statement { + return newStatement().Complex(r, i) +} + +// Complex renders the complex built-in function. +func (g *Group) Complex(r Code, i Code) *Statement { + s := Complex(r, i) + g.items = append(g.items, s) + return s +} + +// Complex renders the complex built-in function. +func (s *Statement) Complex(r Code, i Code) *Statement { + g := &Group{ + close: ")", + items: []Code{r, i}, + multi: false, + name: "complex", + open: "complex(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Copy renders the copy built-in function. +func Copy(dst Code, src Code) *Statement { + return newStatement().Copy(dst, src) +} + +// Copy renders the copy built-in function. +func (g *Group) Copy(dst Code, src Code) *Statement { + s := Copy(dst, src) + g.items = append(g.items, s) + return s +} + +// Copy renders the copy built-in function. +func (s *Statement) Copy(dst Code, src Code) *Statement { + g := &Group{ + close: ")", + items: []Code{dst, src}, + multi: false, + name: "copy", + open: "copy(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Delete renders the delete built-in function. +func Delete(m Code, key Code) *Statement { + return newStatement().Delete(m, key) +} + +// Delete renders the delete built-in function. +func (g *Group) Delete(m Code, key Code) *Statement { + s := Delete(m, key) + g.items = append(g.items, s) + return s +} + +// Delete renders the delete built-in function. +func (s *Statement) Delete(m Code, key Code) *Statement { + g := &Group{ + close: ")", + items: []Code{m, key}, + multi: false, + name: "delete", + open: "delete(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Imag renders the imag built-in function. +func Imag(c Code) *Statement { + return newStatement().Imag(c) +} + +// Imag renders the imag built-in function. +func (g *Group) Imag(c Code) *Statement { + s := Imag(c) + g.items = append(g.items, s) + return s +} + +// Imag renders the imag built-in function. +func (s *Statement) Imag(c Code) *Statement { + g := &Group{ + close: ")", + items: []Code{c}, + multi: false, + name: "imag", + open: "imag(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Len renders the len built-in function. +func Len(v Code) *Statement { + return newStatement().Len(v) +} + +// Len renders the len built-in function. +func (g *Group) Len(v Code) *Statement { + s := Len(v) + g.items = append(g.items, s) + return s +} + +// Len renders the len built-in function. +func (s *Statement) Len(v Code) *Statement { + g := &Group{ + close: ")", + items: []Code{v}, + multi: false, + name: "len", + open: "len(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Make renders the make built-in function. The final parameter of the make function is optional, so it is represented by a variadic parameter list. +func Make(args ...Code) *Statement { + return newStatement().Make(args...) +} + +// Make renders the make built-in function. The final parameter of the make function is optional, so it is represented by a variadic parameter list. +func (g *Group) Make(args ...Code) *Statement { + s := Make(args...) + g.items = append(g.items, s) + return s +} + +// Make renders the make built-in function. The final parameter of the make function is optional, so it is represented by a variadic parameter list. +func (s *Statement) Make(args ...Code) *Statement { + g := &Group{ + close: ")", + items: args, + multi: false, + name: "make", + open: "make(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// New renders the new built-in function. +func New(typ Code) *Statement { + return newStatement().New(typ) +} + +// New renders the new built-in function. +func (g *Group) New(typ Code) *Statement { + s := New(typ) + g.items = append(g.items, s) + return s +} + +// New renders the new built-in function. +func (s *Statement) New(typ Code) *Statement { + g := &Group{ + close: ")", + items: []Code{typ}, + multi: false, + name: "new", + open: "new(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Panic renders the panic built-in function. +func Panic(v Code) *Statement { + return newStatement().Panic(v) +} + +// Panic renders the panic built-in function. +func (g *Group) Panic(v Code) *Statement { + s := Panic(v) + g.items = append(g.items, s) + return s +} + +// Panic renders the panic built-in function. +func (s *Statement) Panic(v Code) *Statement { + g := &Group{ + close: ")", + items: []Code{v}, + multi: false, + name: "panic", + open: "panic(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Print renders the print built-in function. +func Print(args ...Code) *Statement { + return newStatement().Print(args...) +} + +// Print renders the print built-in function. +func (g *Group) Print(args ...Code) *Statement { + s := Print(args...) + g.items = append(g.items, s) + return s +} + +// Print renders the print built-in function. +func (s *Statement) Print(args ...Code) *Statement { + g := &Group{ + close: ")", + items: args, + multi: false, + name: "print", + open: "print(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// PrintFunc renders the print built-in function. +func PrintFunc(f func(*Group)) *Statement { + return newStatement().PrintFunc(f) +} + +// PrintFunc renders the print built-in function. +func (g *Group) PrintFunc(f func(*Group)) *Statement { + s := PrintFunc(f) + g.items = append(g.items, s) + return s +} + +// PrintFunc renders the print built-in function. +func (s *Statement) PrintFunc(f func(*Group)) *Statement { + g := &Group{ + close: ")", + multi: false, + name: "print", + open: "print(", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Println renders the println built-in function. +func Println(args ...Code) *Statement { + return newStatement().Println(args...) +} + +// Println renders the println built-in function. +func (g *Group) Println(args ...Code) *Statement { + s := Println(args...) + g.items = append(g.items, s) + return s +} + +// Println renders the println built-in function. +func (s *Statement) Println(args ...Code) *Statement { + g := &Group{ + close: ")", + items: args, + multi: false, + name: "println", + open: "println(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// PrintlnFunc renders the println built-in function. +func PrintlnFunc(f func(*Group)) *Statement { + return newStatement().PrintlnFunc(f) +} + +// PrintlnFunc renders the println built-in function. +func (g *Group) PrintlnFunc(f func(*Group)) *Statement { + s := PrintlnFunc(f) + g.items = append(g.items, s) + return s +} + +// PrintlnFunc renders the println built-in function. +func (s *Statement) PrintlnFunc(f func(*Group)) *Statement { + g := &Group{ + close: ")", + multi: false, + name: "println", + open: "println(", + separator: ",", + } + f(g) + *s = append(*s, g) + return s +} + +// Real renders the real built-in function. +func Real(c Code) *Statement { + return newStatement().Real(c) +} + +// Real renders the real built-in function. +func (g *Group) Real(c Code) *Statement { + s := Real(c) + g.items = append(g.items, s) + return s +} + +// Real renders the real built-in function. +func (s *Statement) Real(c Code) *Statement { + g := &Group{ + close: ")", + items: []Code{c}, + multi: false, + name: "real", + open: "real(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Recover renders the recover built-in function. +func Recover() *Statement { + return newStatement().Recover() +} + +// Recover renders the recover built-in function. +func (g *Group) Recover() *Statement { + s := Recover() + g.items = append(g.items, s) + return s +} + +// Recover renders the recover built-in function. +func (s *Statement) Recover() *Statement { + g := &Group{ + close: ")", + items: []Code{}, + multi: false, + name: "recover", + open: "recover(", + separator: ",", + } + *s = append(*s, g) + return s +} + +// Bool renders the bool identifier. +func Bool() *Statement { + return newStatement().Bool() +} + +// Bool renders the bool identifier. +func (g *Group) Bool() *Statement { + s := Bool() + g.items = append(g.items, s) + return s +} + +// Bool renders the bool identifier. +func (s *Statement) Bool() *Statement { + t := token{ + content: "bool", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Byte renders the byte identifier. +func Byte() *Statement { + // notest + return newStatement().Byte() +} + +// Byte renders the byte identifier. +func (g *Group) Byte() *Statement { + // notest + s := Byte() + g.items = append(g.items, s) + return s +} + +// Byte renders the byte identifier. +func (s *Statement) Byte() *Statement { + // notest + t := token{ + content: "byte", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Complex64 renders the complex64 identifier. +func Complex64() *Statement { + // notest + return newStatement().Complex64() +} + +// Complex64 renders the complex64 identifier. +func (g *Group) Complex64() *Statement { + // notest + s := Complex64() + g.items = append(g.items, s) + return s +} + +// Complex64 renders the complex64 identifier. +func (s *Statement) Complex64() *Statement { + // notest + t := token{ + content: "complex64", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Complex128 renders the complex128 identifier. +func Complex128() *Statement { + // notest + return newStatement().Complex128() +} + +// Complex128 renders the complex128 identifier. +func (g *Group) Complex128() *Statement { + // notest + s := Complex128() + g.items = append(g.items, s) + return s +} + +// Complex128 renders the complex128 identifier. +func (s *Statement) Complex128() *Statement { + // notest + t := token{ + content: "complex128", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Error renders the error identifier. +func Error() *Statement { + // notest + return newStatement().Error() +} + +// Error renders the error identifier. +func (g *Group) Error() *Statement { + // notest + s := Error() + g.items = append(g.items, s) + return s +} + +// Error renders the error identifier. +func (s *Statement) Error() *Statement { + // notest + t := token{ + content: "error", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Float32 renders the float32 identifier. +func Float32() *Statement { + // notest + return newStatement().Float32() +} + +// Float32 renders the float32 identifier. +func (g *Group) Float32() *Statement { + // notest + s := Float32() + g.items = append(g.items, s) + return s +} + +// Float32 renders the float32 identifier. +func (s *Statement) Float32() *Statement { + // notest + t := token{ + content: "float32", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Float64 renders the float64 identifier. +func Float64() *Statement { + // notest + return newStatement().Float64() +} + +// Float64 renders the float64 identifier. +func (g *Group) Float64() *Statement { + // notest + s := Float64() + g.items = append(g.items, s) + return s +} + +// Float64 renders the float64 identifier. +func (s *Statement) Float64() *Statement { + // notest + t := token{ + content: "float64", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Int renders the int identifier. +func Int() *Statement { + // notest + return newStatement().Int() +} + +// Int renders the int identifier. +func (g *Group) Int() *Statement { + // notest + s := Int() + g.items = append(g.items, s) + return s +} + +// Int renders the int identifier. +func (s *Statement) Int() *Statement { + // notest + t := token{ + content: "int", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Int8 renders the int8 identifier. +func Int8() *Statement { + // notest + return newStatement().Int8() +} + +// Int8 renders the int8 identifier. +func (g *Group) Int8() *Statement { + // notest + s := Int8() + g.items = append(g.items, s) + return s +} + +// Int8 renders the int8 identifier. +func (s *Statement) Int8() *Statement { + // notest + t := token{ + content: "int8", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Int16 renders the int16 identifier. +func Int16() *Statement { + // notest + return newStatement().Int16() +} + +// Int16 renders the int16 identifier. +func (g *Group) Int16() *Statement { + // notest + s := Int16() + g.items = append(g.items, s) + return s +} + +// Int16 renders the int16 identifier. +func (s *Statement) Int16() *Statement { + // notest + t := token{ + content: "int16", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Int32 renders the int32 identifier. +func Int32() *Statement { + // notest + return newStatement().Int32() +} + +// Int32 renders the int32 identifier. +func (g *Group) Int32() *Statement { + // notest + s := Int32() + g.items = append(g.items, s) + return s +} + +// Int32 renders the int32 identifier. +func (s *Statement) Int32() *Statement { + // notest + t := token{ + content: "int32", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Int64 renders the int64 identifier. +func Int64() *Statement { + // notest + return newStatement().Int64() +} + +// Int64 renders the int64 identifier. +func (g *Group) Int64() *Statement { + // notest + s := Int64() + g.items = append(g.items, s) + return s +} + +// Int64 renders the int64 identifier. +func (s *Statement) Int64() *Statement { + // notest + t := token{ + content: "int64", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Rune renders the rune identifier. +func Rune() *Statement { + // notest + return newStatement().Rune() +} + +// Rune renders the rune identifier. +func (g *Group) Rune() *Statement { + // notest + s := Rune() + g.items = append(g.items, s) + return s +} + +// Rune renders the rune identifier. +func (s *Statement) Rune() *Statement { + // notest + t := token{ + content: "rune", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// String renders the string identifier. +func String() *Statement { + // notest + return newStatement().String() +} + +// String renders the string identifier. +func (g *Group) String() *Statement { + // notest + s := String() + g.items = append(g.items, s) + return s +} + +// String renders the string identifier. +func (s *Statement) String() *Statement { + // notest + t := token{ + content: "string", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Uint renders the uint identifier. +func Uint() *Statement { + // notest + return newStatement().Uint() +} + +// Uint renders the uint identifier. +func (g *Group) Uint() *Statement { + // notest + s := Uint() + g.items = append(g.items, s) + return s +} + +// Uint renders the uint identifier. +func (s *Statement) Uint() *Statement { + // notest + t := token{ + content: "uint", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Uint8 renders the uint8 identifier. +func Uint8() *Statement { + // notest + return newStatement().Uint8() +} + +// Uint8 renders the uint8 identifier. +func (g *Group) Uint8() *Statement { + // notest + s := Uint8() + g.items = append(g.items, s) + return s +} + +// Uint8 renders the uint8 identifier. +func (s *Statement) Uint8() *Statement { + // notest + t := token{ + content: "uint8", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Uint16 renders the uint16 identifier. +func Uint16() *Statement { + // notest + return newStatement().Uint16() +} + +// Uint16 renders the uint16 identifier. +func (g *Group) Uint16() *Statement { + // notest + s := Uint16() + g.items = append(g.items, s) + return s +} + +// Uint16 renders the uint16 identifier. +func (s *Statement) Uint16() *Statement { + // notest + t := token{ + content: "uint16", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Uint32 renders the uint32 identifier. +func Uint32() *Statement { + // notest + return newStatement().Uint32() +} + +// Uint32 renders the uint32 identifier. +func (g *Group) Uint32() *Statement { + // notest + s := Uint32() + g.items = append(g.items, s) + return s +} + +// Uint32 renders the uint32 identifier. +func (s *Statement) Uint32() *Statement { + // notest + t := token{ + content: "uint32", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Uint64 renders the uint64 identifier. +func Uint64() *Statement { + // notest + return newStatement().Uint64() +} + +// Uint64 renders the uint64 identifier. +func (g *Group) Uint64() *Statement { + // notest + s := Uint64() + g.items = append(g.items, s) + return s +} + +// Uint64 renders the uint64 identifier. +func (s *Statement) Uint64() *Statement { + // notest + t := token{ + content: "uint64", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Uintptr renders the uintptr identifier. +func Uintptr() *Statement { + // notest + return newStatement().Uintptr() +} + +// Uintptr renders the uintptr identifier. +func (g *Group) Uintptr() *Statement { + // notest + s := Uintptr() + g.items = append(g.items, s) + return s +} + +// Uintptr renders the uintptr identifier. +func (s *Statement) Uintptr() *Statement { + // notest + t := token{ + content: "uintptr", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// True renders the true identifier. +func True() *Statement { + // notest + return newStatement().True() +} + +// True renders the true identifier. +func (g *Group) True() *Statement { + // notest + s := True() + g.items = append(g.items, s) + return s +} + +// True renders the true identifier. +func (s *Statement) True() *Statement { + // notest + t := token{ + content: "true", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// False renders the false identifier. +func False() *Statement { + // notest + return newStatement().False() +} + +// False renders the false identifier. +func (g *Group) False() *Statement { + // notest + s := False() + g.items = append(g.items, s) + return s +} + +// False renders the false identifier. +func (s *Statement) False() *Statement { + // notest + t := token{ + content: "false", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Iota renders the iota identifier. +func Iota() *Statement { + // notest + return newStatement().Iota() +} + +// Iota renders the iota identifier. +func (g *Group) Iota() *Statement { + // notest + s := Iota() + g.items = append(g.items, s) + return s +} + +// Iota renders the iota identifier. +func (s *Statement) Iota() *Statement { + // notest + t := token{ + content: "iota", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Nil renders the nil identifier. +func Nil() *Statement { + // notest + return newStatement().Nil() +} + +// Nil renders the nil identifier. +func (g *Group) Nil() *Statement { + // notest + s := Nil() + g.items = append(g.items, s) + return s +} + +// Nil renders the nil identifier. +func (s *Statement) Nil() *Statement { + // notest + t := token{ + content: "nil", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Err renders the err identifier. +func Err() *Statement { + // notest + return newStatement().Err() +} + +// Err renders the err identifier. +func (g *Group) Err() *Statement { + // notest + s := Err() + g.items = append(g.items, s) + return s +} + +// Err renders the err identifier. +func (s *Statement) Err() *Statement { + // notest + t := token{ + content: "err", + typ: identifierToken, + } + *s = append(*s, t) + return s +} + +// Break renders the break keyword. +func Break() *Statement { + // notest + return newStatement().Break() +} + +// Break renders the break keyword. +func (g *Group) Break() *Statement { + // notest + s := Break() + g.items = append(g.items, s) + return s +} + +// Break renders the break keyword. +func (s *Statement) Break() *Statement { + // notest + t := token{ + content: "break", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Default renders the default keyword. +func Default() *Statement { + // notest + return newStatement().Default() +} + +// Default renders the default keyword. +func (g *Group) Default() *Statement { + // notest + s := Default() + g.items = append(g.items, s) + return s +} + +// Default renders the default keyword. +func (s *Statement) Default() *Statement { + // notest + t := token{ + content: "default", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Func renders the func keyword. +func Func() *Statement { + // notest + return newStatement().Func() +} + +// Func renders the func keyword. +func (g *Group) Func() *Statement { + // notest + s := Func() + g.items = append(g.items, s) + return s +} + +// Func renders the func keyword. +func (s *Statement) Func() *Statement { + // notest + t := token{ + content: "func", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Select renders the select keyword. +func Select() *Statement { + // notest + return newStatement().Select() +} + +// Select renders the select keyword. +func (g *Group) Select() *Statement { + // notest + s := Select() + g.items = append(g.items, s) + return s +} + +// Select renders the select keyword. +func (s *Statement) Select() *Statement { + // notest + t := token{ + content: "select", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Chan renders the chan keyword. +func Chan() *Statement { + // notest + return newStatement().Chan() +} + +// Chan renders the chan keyword. +func (g *Group) Chan() *Statement { + // notest + s := Chan() + g.items = append(g.items, s) + return s +} + +// Chan renders the chan keyword. +func (s *Statement) Chan() *Statement { + // notest + t := token{ + content: "chan", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Else renders the else keyword. +func Else() *Statement { + // notest + return newStatement().Else() +} + +// Else renders the else keyword. +func (g *Group) Else() *Statement { + // notest + s := Else() + g.items = append(g.items, s) + return s +} + +// Else renders the else keyword. +func (s *Statement) Else() *Statement { + // notest + t := token{ + content: "else", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Const renders the const keyword. +func Const() *Statement { + // notest + return newStatement().Const() +} + +// Const renders the const keyword. +func (g *Group) Const() *Statement { + // notest + s := Const() + g.items = append(g.items, s) + return s +} + +// Const renders the const keyword. +func (s *Statement) Const() *Statement { + // notest + t := token{ + content: "const", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Fallthrough renders the fallthrough keyword. +func Fallthrough() *Statement { + // notest + return newStatement().Fallthrough() +} + +// Fallthrough renders the fallthrough keyword. +func (g *Group) Fallthrough() *Statement { + // notest + s := Fallthrough() + g.items = append(g.items, s) + return s +} + +// Fallthrough renders the fallthrough keyword. +func (s *Statement) Fallthrough() *Statement { + // notest + t := token{ + content: "fallthrough", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Type renders the type keyword. +func Type() *Statement { + // notest + return newStatement().Type() +} + +// Type renders the type keyword. +func (g *Group) Type() *Statement { + // notest + s := Type() + g.items = append(g.items, s) + return s +} + +// Type renders the type keyword. +func (s *Statement) Type() *Statement { + // notest + t := token{ + content: "type", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Continue renders the continue keyword. +func Continue() *Statement { + // notest + return newStatement().Continue() +} + +// Continue renders the continue keyword. +func (g *Group) Continue() *Statement { + // notest + s := Continue() + g.items = append(g.items, s) + return s +} + +// Continue renders the continue keyword. +func (s *Statement) Continue() *Statement { + // notest + t := token{ + content: "continue", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Var renders the var keyword. +func Var() *Statement { + // notest + return newStatement().Var() +} + +// Var renders the var keyword. +func (g *Group) Var() *Statement { + // notest + s := Var() + g.items = append(g.items, s) + return s +} + +// Var renders the var keyword. +func (s *Statement) Var() *Statement { + // notest + t := token{ + content: "var", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Goto renders the goto keyword. +func Goto() *Statement { + // notest + return newStatement().Goto() +} + +// Goto renders the goto keyword. +func (g *Group) Goto() *Statement { + // notest + s := Goto() + g.items = append(g.items, s) + return s +} + +// Goto renders the goto keyword. +func (s *Statement) Goto() *Statement { + // notest + t := token{ + content: "goto", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Defer renders the defer keyword. +func Defer() *Statement { + // notest + return newStatement().Defer() +} + +// Defer renders the defer keyword. +func (g *Group) Defer() *Statement { + // notest + s := Defer() + g.items = append(g.items, s) + return s +} + +// Defer renders the defer keyword. +func (s *Statement) Defer() *Statement { + // notest + t := token{ + content: "defer", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Go renders the go keyword. +func Go() *Statement { + // notest + return newStatement().Go() +} + +// Go renders the go keyword. +func (g *Group) Go() *Statement { + // notest + s := Go() + g.items = append(g.items, s) + return s +} + +// Go renders the go keyword. +func (s *Statement) Go() *Statement { + // notest + t := token{ + content: "go", + typ: keywordToken, + } + *s = append(*s, t) + return s +} + +// Range renders the range keyword. +func Range() *Statement { + // notest + return newStatement().Range() +} + +// Range renders the range keyword. +func (g *Group) Range() *Statement { + // notest + s := Range() + g.items = append(g.items, s) + return s +} + +// Range renders the range keyword. +func (s *Statement) Range() *Statement { + // notest + t := token{ + content: "range", + typ: keywordToken, + } + *s = append(*s, t) + return s +} diff --git a/vendor/github.com/dave/jennifer/jen/generated_test.go b/vendor/github.com/dave/jennifer/jen/generated_test.go new file mode 100644 index 00000000..fce14c70 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/generated_test.go @@ -0,0 +1,808 @@ +package jen_test + +import ( + "testing" + + . "github.com/dave/jennifer/jen" +) + +var gencases = []tc{ + { + desc: `bool group`, + code: BlockFunc(func(g *Group) { + g.Bool() + }), + expect: `{ + bool + }`, + }, + { + desc: `recover func`, + code: Recover(), + expect: `recover()`, + }, + { + desc: `recover statement`, + code: Null().Recover(), + expect: `recover()`, + }, + { + desc: `recover group`, + code: BlockFunc(func(g *Group) { + g.Recover() + }), + expect: `{ + recover() + }`, + }, + { + desc: `real func`, + code: Real(Id("a")), + expect: `real(a)`, + }, + { + desc: `real statement`, + code: Null().Real(Id("a")), + expect: `real(a)`, + }, + { + desc: `real group`, + code: BlockFunc(func(g *Group) { + g.Real(Id("a")) + }), + expect: `{ + real(a) + }`, + }, + { + desc: `printlnfunc func`, + code: PrintlnFunc(func(g *Group) { g.Id("a") }), + expect: `println(a)`, + }, + { + desc: `printlnfunc statement`, + code: Null().PrintlnFunc(func(g *Group) { g.Id("a") }), + expect: `println(a)`, + }, + { + desc: `printlnfunc group`, + code: BlockFunc(func(bg *Group) { + bg.PrintlnFunc(func(pg *Group) { pg.Id("a") }) + }), + expect: `{ + println(a) + }`, + }, + { + desc: `println func`, + code: Println(Id("a")), + expect: `println(a)`, + }, + { + desc: `println statement`, + code: Null().Println(Id("a")), + expect: `println(a)`, + }, + { + desc: `println group`, + code: BlockFunc(func(g *Group) { + g.Println(Id("a")) + }), + expect: `{ + println(a) + }`, + }, + { + desc: `printfunc func`, + code: PrintFunc(func(g *Group) { g.Id("a") }), + expect: `print(a)`, + }, + { + desc: `printfunc statement`, + code: Null().PrintFunc(func(g *Group) { g.Id("a") }), + expect: `print(a)`, + }, + { + desc: `printfunc group`, + code: BlockFunc(func(bg *Group) { + bg.PrintFunc(func(pg *Group) { pg.Id("a") }) + }), + expect: `{ + print(a) + }`, + }, + { + desc: `print func`, + code: Print(Id("a")), + expect: `print(a)`, + }, + { + desc: `print statement`, + code: Null().Print(Id("a")), + expect: `print(a)`, + }, + { + desc: `print group`, + code: BlockFunc(func(g *Group) { + g.Print(Id("a")) + }), + expect: `{ + print(a) + }`, + }, + { + desc: `panic func`, + code: Panic(Id("a")), + expect: `panic(a)`, + }, + { + desc: `panic statement`, + code: Null().Panic(Id("a")), + expect: `panic(a)`, + }, + { + desc: `panic group`, + code: BlockFunc(func(g *Group) { + g.Panic(Id("a")) + }), + expect: `{ + panic(a) + }`, + }, + { + desc: `new func`, + code: New(Id("a")), + expect: `new(a)`, + }, + { + desc: `new statement`, + code: Id("a").Op(":=").New(Id("a")), + expect: `a := new(a)`, + }, + { + desc: `new group`, + code: BlockFunc(func(g *Group) { + g.New(Id("a")) + }), + expect: `{ + new(a) + }`, + }, + { + desc: `make func`, + code: Make(Id("a")), + expect: `make(a)`, + }, + { + desc: `make statement`, + code: Id("a").Op(":=").Make(Id("a")), + expect: `a := make(a)`, + }, + { + desc: `make group`, + code: BlockFunc(func(g *Group) { + g.Make(Id("a")) + }), + expect: `{ + make(a) + }`, + }, + { + desc: `len func`, + code: Len(Id("a")), + expect: `len(a)`, + }, + { + desc: `len statement`, + code: Id("a").Op(":=").Len(Id("a")), + expect: `a := len(a)`, + }, + { + desc: `len group`, + code: BlockFunc(func(g *Group) { + g.Len(Id("a")) + }), + expect: `{ + len(a) + }`, + }, + { + desc: `imag func`, + code: Imag(Id("a")), + expect: `imag(a)`, + }, + { + desc: `imag statement`, + code: Id("a").Op(":=").Imag(Id("a")), + expect: `a := imag(a)`, + }, + { + desc: `imag group`, + code: BlockFunc(func(g *Group) { + g.Imag(Id("a")) + }), + expect: `{ + imag(a) + }`, + }, + { + desc: `delete func`, + code: Delete(Id("a"), Id("b")), + expect: `delete(a, b)`, + }, + { + desc: `delete statement`, + code: Null().Delete(Id("a"), Id("b")), + expect: `delete(a, b)`, + }, + { + desc: `delete group`, + code: BlockFunc(func(g *Group) { + g.Delete(Id("a"), Id("b")) + }), + expect: `{ + delete(a, b) + }`, + }, + { + desc: `copy func`, + code: Copy(Id("a"), Id("b")), + expect: `copy(a, b)`, + }, + { + desc: `copy statement`, + code: Id("a").Op(":=").Copy(Id("a"), Id("b")), + expect: `a := copy(a, b)`, + }, + { + desc: `copy group`, + code: BlockFunc(func(g *Group) { + g.Copy(Id("a"), Id("b")) + }), + expect: `{ + copy(a, b) + }`, + }, + { + desc: `complex func`, + code: Complex(Id("a"), Id("b")), + expect: `complex(a, b)`, + }, + { + desc: `complex statement`, + code: Id("a").Op(":=").Complex(Id("a"), Id("b")), + expect: `a := complex(a, b)`, + }, + { + desc: `complex group`, + code: BlockFunc(func(g *Group) { + g.Complex(Id("a"), Id("b")) + }), + expect: `{ + complex(a, b) + }`, + }, + { + desc: `close group`, + code: BlockFunc(func(g *Group) { g.Close(Id("a")) }), + expect: `{ + close(a) + }`, + }, + { + desc: `cap func`, + code: Cap(Id("a")), + expect: `cap(a)`, + }, + { + desc: `cap statement`, + code: Id("a").Op(":=").Cap(Id("b")), + expect: `a := cap(b)`, + }, + { + desc: `cap group`, + code: BlockFunc(func(g *Group) { + g.Cap(Id("a")) + }), + expect: `{ + cap(a) + }`, + }, + { + desc: `append group`, + code: BlockFunc(func(g *Group) { + g.Append(Id("a")) + }), + expect: `{ + append(a) + }`, + }, + { + desc: `appendfunc statement`, + code: Id("a").Op("=").AppendFunc(func(ag *Group) { ag.Id("a") }), + expect: `a = append(a)`, + }, + { + desc: `appendfunc func`, + code: AppendFunc(func(ag *Group) { ag.Id("a") }), + expect: `append(a)`, + }, + { + desc: `appendfunc group`, + code: BlockFunc(func(bg *Group) { + bg.AppendFunc(func(ag *Group) { ag.Id("a") }) + }), + expect: `{ + append(a) + }`, + }, + { + desc: `casefunc group`, + code: Switch().BlockFunc(func(g *Group) { + g.CaseFunc(func(g *Group) { g.Id("a") }).Block() + }), + expect: `switch { + case a: + }`, + }, + { + desc: `case group`, + code: Switch().BlockFunc(func(g *Group) { + g.Case(Id("a")).Block() + }), + expect: `switch { + case a: + }`, + }, + { + desc: `structfunc statement`, + code: Id("a").Op(":=").StructFunc(func(g *Group) {}).Values(), + expect: `a := struct{}{}`, + }, + { + desc: `structfunc group`, + // Don't do this! ListFunc used to kludge Group.Struct usage + // without syntax error. + code: Id("a").Op(":=").ListFunc(func(g *Group) { g.StructFunc(func(g *Group) {}) }).Values(), + expect: `a := struct{}{}`, + }, + { + desc: `structfunc func`, + code: Id("a").Op(":=").Add(StructFunc(func(g *Group) {})).Values(), + expect: `a := struct{}{}`, + }, + { + desc: `struct group`, + // Don't do this! ListFunc used to kludge Group.Struct usage + // without syntax error. + code: Id("a").Op(":=").ListFunc(func(g *Group) { g.Struct() }).Values(), + expect: `a := struct{}{}`, + }, + { + desc: `struct func`, + code: Id("a").Op(":=").Add(Struct()).Values(), + expect: `a := struct{}{}`, + }, + { + desc: `interfacefunc func`, + code: Id("a").Assert(InterfaceFunc(func(g *Group) { + g.Id("a").Call().Int() + g.Id("b").Call().Int() + })), + expect: `a.(interface{ + a() int + b() int + })`, + }, + { + desc: `interfacefunc statement`, + code: Id("a").Assert(Null().InterfaceFunc(func(g *Group) { + g.Id("a").Call().Int() + g.Id("b").Call().Int() + })), + expect: `a.(interface{ + a() int + b() int + })`, + }, + { + desc: `interfacefunc group`, + // Don't do this! ListFunc used to kludge Group.InterfaceFunc usage + // without syntax error. + code: Id("a").Assert(ListFunc(func(lg *Group) { + lg.InterfaceFunc(func(ig *Group) { + ig.Id("a").Call().Int() + ig.Id("b").Call().Int() + }) + })), + expect: `a.(interface{ + a() int + b() int + })`, + }, + { + desc: `interface func`, + code: Interface().Parens(Id("a")), + expect: `interface{}(a)`, + }, + { + desc: `interface group`, + code: BlockFunc(func(g *Group) { + g.Interface().Parens(Id("a")) + }), + expect: `{ + interface{}(a) + }`, + }, + { + desc: `interface statement`, + code: Null().Interface().Parens(Id("a")), + expect: `interface{}(a)`, + }, + { + desc: `switchfunc func`, + code: SwitchFunc(func(rg *Group) { + rg.Id("a") + }).Block(), + expect: `switch a {}`, + }, + { + desc: `switchfunc statement`, + code: Null().SwitchFunc(func(rg *Group) { + rg.Id("a") + }).Block(), + expect: `switch a { + }`, + }, + { + desc: `switchfunc group`, + code: BlockFunc(func(bg *Group) { + bg.SwitchFunc(func(rg *Group) { + rg.Id("a") + }).Block() + }), + expect: `{ + switch a { + } + }`, + }, + { + desc: `switch group`, + code: BlockFunc(func(bg *Group) { + bg.Switch().Block() + }), + expect: `{ + switch { + } + }`, + }, + { + desc: `forfunc func`, + code: ForFunc(func(rg *Group) { + rg.Id("a") + }).Block(), + expect: `for a {}`, + }, + { + desc: `forfunc statement`, + code: Null().ForFunc(func(rg *Group) { + rg.Id("a") + }).Block(), + expect: `for a { + }`, + }, + { + desc: `forfunc group`, + code: BlockFunc(func(bg *Group) { + bg.ForFunc(func(rg *Group) { + rg.Id("a") + }).Block() + }), + expect: `{ + for a { + } + }`, + }, + { + desc: `for group`, + code: BlockFunc(func(g *Group) { + g.For(Id("a")).Block() + }), + expect: `{ + for a {} + }`, + }, + { + desc: `returnfunc func`, + code: ReturnFunc(func(rg *Group) { + rg.Lit(1) + rg.Lit(2) + }), + expect: `return 1, 2`, + }, + { + desc: `returnfunc statement`, + code: Empty().ReturnFunc(func(rg *Group) { + rg.Lit(1) + rg.Lit(2) + }), + expect: `return 1, 2`, + }, + { + desc: `returnfunc group`, + code: BlockFunc(func(bg *Group) { + bg.ReturnFunc(func(rg *Group) { + rg.Lit(1) + rg.Lit(2) + }) + }), + expect: `{ + return 1, 2 + }`, + }, + { + desc: `return group`, + code: BlockFunc(func(g *Group) { + g.Return() + }), + expect: `{ + return + }`, + }, + { + desc: `iffunc group`, + code: BlockFunc(func(bg *Group) { + bg.IfFunc(func(ig *Group) { + ig.Id("a") + }).Block() + }), + expect: `{ + if a {} + }`, + }, + { + desc: `iffunc func`, + code: IfFunc(func(ig *Group) { + ig.Id("a") + }).Block(), + expect: `if a {}`, + }, + { + desc: `iffunc statement`, + code: Null().IfFunc(func(ig *Group) { + ig.Id("a") + }).Block(), + expect: `if a {}`, + }, + { + desc: `if group`, + code: BlockFunc(func(g *Group) { g.If(Id("a")).Block() }), + expect: `{ + if a {} + }`, + }, + { + desc: `map group`, + code: BlockFunc(func(g *Group) { g.Map(Int()).Int().Values(Dict{Lit(1): Lit(1)}) }), + expect: `{ + map[int]int{1:1} + }`, + }, + { + desc: `assert group`, + // Don't do this! ListFunc used to kludge Group.Assert usage without + // syntax error. + code: Id("a").ListFunc(func(g *Group) { g.Assert(Id("b")) }), + expect: `a.(b)`, + }, + { + desc: `assert func`, + code: Id("a").Add(Assert(Id("b"))), + expect: `a.(b)`, + }, + { + desc: `paramsfunc group`, + // Don't do this! ListFunc used to kludge Group.ParamsFunc usage without + // syntax error. + code: Id("a").ListFunc(func(lg *Group) { lg.ParamsFunc(func(cg *Group) { cg.Lit(1) }) }), + expect: `a(1)`, + }, + { + desc: `paramsfunc func`, + code: Id("a").Add(ParamsFunc(func(g *Group) { g.Lit(1) })), + expect: `a(1)`, + }, + { + desc: `paramsfunc statement`, + code: Id("a").ParamsFunc(func(g *Group) { g.Lit(1) }), + expect: `a(1)`, + }, + { + desc: `params group`, + // Don't do this! ListFunc used to kludge Group.Params usage without + // syntax error. + code: Id("a").ListFunc(func(g *Group) { g.Params(Lit(1)) }), + expect: `a(1)`, + }, + { + desc: `params func`, + code: Id("a").Add(Params(Lit(1))), + expect: `a(1)`, + }, + { + desc: `callfunc group`, + // Don't do this! ListFunc used to kludge Group.CallFunc usage without + // syntax error. + code: Id("a").ListFunc(func(lg *Group) { lg.CallFunc(func(cg *Group) { cg.Lit(1) }) }), + expect: `a(1)`, + }, + { + desc: `callfunc func`, + code: Id("a").Add(CallFunc(func(g *Group) { g.Lit(1) })), + expect: `a(1)`, + }, + { + desc: `call group`, + // Don't do this! ListFunc used to kludge Group.Call usage without + // syntax error. + code: Id("a").ListFunc(func(g *Group) { g.Call(Lit(1)) }), + expect: `a(1)`, + }, + { + desc: `call func`, + code: Id("a").Add(Call(Lit(1))), + expect: `a(1)`, + }, + { + desc: `defsfunc statement`, + code: Const().DefsFunc(func(g *Group) { g.Id("a").Op("=").Lit(1) }), + expect: `const ( + a = 1 + )`, + }, + { + desc: `defsfunc func`, + code: Const().Add(DefsFunc(func(g *Group) { g.Id("a").Op("=").Lit(1) })), + expect: `const ( + a = 1 + )`, + }, + { + desc: `defsfunc group`, + // Don't do this! ListFunc used to kludge Group.DefsFunc usage without + // syntax error. + code: Const().ListFunc(func(lg *Group) { lg.DefsFunc(func(dg *Group) { dg.Id("a").Op("=").Lit(1) }) }), + expect: `const ( + a = 1 + )`, + }, + { + desc: `defs group`, + // Don't do this! ListFunc used to kludge Group.Defs usage without + // syntax error. + code: Const().ListFunc(func(g *Group) { g.Defs(Id("a").Op("=").Lit(1)) }), + expect: `const ( + a = 1 + )`, + }, + { + desc: `defs func`, + code: Const().Add(Defs(Id("a").Op("=").Lit(1))), + expect: `const ( + a = 1 + )`, + }, + { + desc: `blockfunc group`, + code: BlockFunc(func(g *Group) { g.BlockFunc(func(g *Group) {}) }), + expect: `{{}}`, + }, + { + desc: `block group`, + code: BlockFunc(func(g *Group) { g.Block() }), + expect: `{{}}`, + }, + { + desc: `indexfunc group`, + code: BlockFunc(func(g *Group) { g.IndexFunc(func(g *Group) { g.Lit(1) }).Int().Values(Lit(1)) }), + expect: `{[1]int{1}}`, + }, + { + desc: `indexfunc statement`, + code: Id("a").IndexFunc(func(g *Group) { g.Lit(1) }), + expect: `a[1]`, + }, + { + desc: `indexfunc func`, + code: Id("a").Add(IndexFunc(func(g *Group) { g.Lit(1) })), + expect: `a[1]`, + }, + { + desc: `index group`, + code: BlockFunc(func(g *Group) { g.Index(Lit(1)).Int().Values(Lit(1)) }), + expect: `{[1]int{1}}`, + }, + { + desc: `index func`, + code: Id("a").Add(Index(Lit(1))), + expect: `a[1]`, + }, + { + desc: `valuesfunc func`, + code: ValuesFunc(func(vg *Group) { + vg.Lit(1) + }), + expect: `{1}`, + }, + { + desc: `valuesfunc group`, + code: BlockFunc(func(bg *Group) { + bg.ValuesFunc(func(vg *Group) { + vg.Lit(1) + }) + }), + expect: `{ + {1} + }`, + }, + { + desc: `values group`, + code: BlockFunc(func(g *Group) { + g.Values(Lit(1)) + }), + expect: `{ + {1} + }`, + }, + { + desc: `listfunc statement`, + code: Add(Null()).ListFunc(func(lg *Group) { + lg.Id("a") + lg.Id("b") + }).Op("=").Id("c"), + expect: `a, b = c`, + }, + { + desc: `listfunc func`, + code: ListFunc(func(lg *Group) { + lg.Id("a") + lg.Id("b") + }).Op("=").Id("c"), + expect: `a, b = c`, + }, + { + desc: `listfunc group`, + code: BlockFunc(func(bg *Group) { + bg.ListFunc(func(lg *Group) { + lg.Id("a") + lg.Id("b") + }).Op("=").Id("c") + }), + expect: `{ + a, b = c + }`, + }, + { + desc: `list group`, + code: BlockFunc(func(g *Group) { g.List(Id("a"), Id("b")).Op("=").Id("c") }), + expect: `{ + a, b = c + }`, + }, + { + desc: `parens func`, + code: Parens(Lit(1)), + expect: `(1)`, + }, + { + desc: `parens group`, + code: BlockFunc(func(g *Group) { g.Parens(Lit(1)) }), + expect: `{ + (1) + }`, + }, +} + +func TestGen(t *testing.T) { + caseTester(t, gencases) +} diff --git a/vendor/github.com/dave/jennifer/jen/group.go b/vendor/github.com/dave/jennifer/jen/group.go new file mode 100644 index 00000000..0b85c901 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/group.go @@ -0,0 +1,147 @@ +package jen + +import ( + "bytes" + "fmt" + "go/format" + "io" +) + +// Group represents a list of Code items, separated by tokens with an optional +// open and close token. +type Group struct { + name string + items []Code + open string + close string + separator string + multi bool +} + +func (g *Group) isNull(f *File) bool { + if g == nil { + return true + } + if g.open != "" || g.close != "" { + return false + } + for _, c := range g.items { + if !c.isNull(f) { + return false + } + } + return true +} + +func (g *Group) render(f *File, w io.Writer, s *Statement) error { + if g.name == "block" && s != nil { + // Special CaseBlock format for then the previous item in the statement + // is a Case group or the default keyword. + prev := s.previous(g) + grp, isGrp := prev.(*Group) + tkn, isTkn := prev.(token) + if isGrp && grp.name == "case" || isTkn && tkn.content == "default" { + g.open = "" + g.close = "" + } + } + if g.open != "" { + if _, err := w.Write([]byte(g.open)); err != nil { + return err + } + } + isNull, err := g.renderItems(f, w) + if err != nil { + return err + } + if !isNull && g.multi && g.close != "" { + // For multi-line blocks with a closing token, we insert a new line after the last item (but + // not if all items were null). This is to ensure that if the statement finishes with a comment, + // the closing token is not commented out. + s := "\n" + if g.separator == "," { + // We also insert add trailing comma if the separator was ",". + s = ",\n" + } + if _, err := w.Write([]byte(s)); err != nil { + return err + } + } + if g.close != "" { + if _, err := w.Write([]byte(g.close)); err != nil { + return err + } + } + return nil +} + +func (g *Group) renderItems(f *File, w io.Writer) (isNull bool, err error) { + first := true + for _, code := range g.items { + if pt, ok := code.(token); ok && pt.typ == packageToken { + // Special case for package tokens in Qual groups - for dot-imports, the package token + // will be null, so will not render and will not be registered in the imports block. + // This ensures all packageTokens that are rendered are registered. + f.register(pt.content.(string)) + } + if code == nil || code.isNull(f) { + // Null() token produces no output but also + // no separator. Empty() token products no + // output but adds a separator. + continue + } + if g.name == "values" { + if _, ok := code.(Dict); ok && len(g.items) > 1 { + panic("Error in Values: if Dict is used, must be one item only") + } + } + if !first && g.separator != "" { + // The separator token is added before each non-null item, but not before the first item. + if _, err := w.Write([]byte(g.separator)); err != nil { + return false, err + } + } + if g.multi { + // For multi-line blocks, we insert a new line before each non-null item. + if _, err := w.Write([]byte("\n")); err != nil { + return false, err + } + } + if err := code.render(f, w, nil); err != nil { + return false, err + } + first = false + } + return first, nil +} + +// Render renders the Group to the provided writer. +func (g *Group) Render(writer io.Writer) error { + return g.RenderWithFile(writer, NewFile("")) +} + +// GoString renders the Group for testing. Any error will cause a panic. +func (g *Group) GoString() string { + buf := bytes.Buffer{} + if err := g.Render(&buf); err != nil { + panic(err) + } + return buf.String() +} + +// RenderWithFile renders the Group to the provided writer, using imports from the provided file. +func (g *Group) RenderWithFile(writer io.Writer, file *File) error { + buf := &bytes.Buffer{} + if err := g.render(file, buf, nil); err != nil { + return err + } + b, err := format.Source(buf.Bytes()) + if err != nil { + return fmt.Errorf("Error %s while formatting source:\n%s", err, buf.String()) + } + if _, err := writer.Write(b); err != nil { + return err + } + return nil +} + diff --git a/vendor/github.com/dave/jennifer/jen/group_test.go b/vendor/github.com/dave/jennifer/jen/group_test.go new file mode 100644 index 00000000..0e9489e4 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/group_test.go @@ -0,0 +1,35 @@ +package jen_test + +import ( + "bytes" + "testing" + + . "github.com/dave/jennifer/jen" +) + +func TestGroup_Render(t *testing.T) { + file := NewFile("main") + file.ImportAlias("fmt", "fmtalias") + + var g *Group + BlockFunc(func(group *Group) { + g = group + }) + + g.Qual("fmt", "Errorf").Call(Lit("error")) + + expect := `{ + fmtalias.Errorf("error") +}` + + var got bytes.Buffer + + err := g.RenderWithFile(&got, file) + if err != nil { + t.Fatal(err) + } + + if got.String() != expect { + t.Fatalf("Got: %v, expect: %v", got.String(), expect) + } +} diff --git a/vendor/github.com/dave/jennifer/jen/hints.go b/vendor/github.com/dave/jennifer/jen/hints.go new file mode 100644 index 00000000..7bc307a6 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/hints.go @@ -0,0 +1,273 @@ +// This file is generated - do not edit. + +package jen + +// standardLibraryHints contains package name hints +var standardLibraryHints = map[string]string{ + "archive/tar": "tar", + "archive/zip": "zip", + "bufio": "bufio", + "builtin": "builtin", + "bytes": "bytes", + "cmd/asm/internal/arch": "arch", + "cmd/asm/internal/asm": "asm", + "cmd/asm/internal/flags": "flags", + "cmd/asm/internal/lex": "lex", + "cmd/compile/internal/amd64": "amd64", + "cmd/compile/internal/arm": "arm", + "cmd/compile/internal/arm64": "arm64", + "cmd/compile/internal/gc": "gc", + "cmd/compile/internal/mips": "mips", + "cmd/compile/internal/mips64": "mips64", + "cmd/compile/internal/ppc64": "ppc64", + "cmd/compile/internal/s390x": "s390x", + "cmd/compile/internal/ssa": "ssa", + "cmd/compile/internal/syntax": "syntax", + "cmd/compile/internal/test": "test", + "cmd/compile/internal/types": "types", + "cmd/compile/internal/wasm": "wasm", + "cmd/compile/internal/x86": "x86", + "cmd/go/internal/base": "base", + "cmd/go/internal/bug": "bug", + "cmd/go/internal/cache": "cache", + "cmd/go/internal/cfg": "cfg", + "cmd/go/internal/clean": "clean", + "cmd/go/internal/cmdflag": "cmdflag", + "cmd/go/internal/dirhash": "dirhash", + "cmd/go/internal/doc": "doc", + "cmd/go/internal/envcmd": "envcmd", + "cmd/go/internal/fix": "fix", + "cmd/go/internal/fmtcmd": "fmtcmd", + "cmd/go/internal/generate": "generate", + "cmd/go/internal/get": "get", + "cmd/go/internal/help": "help", + "cmd/go/internal/imports": "imports", + "cmd/go/internal/list": "list", + "cmd/go/internal/load": "load", + "cmd/go/internal/modcmd": "modcmd", + "cmd/go/internal/modconv": "modconv", + "cmd/go/internal/modfetch": "modfetch", + "cmd/go/internal/modfetch/codehost": "codehost", + "cmd/go/internal/modfile": "modfile", + "cmd/go/internal/modget": "modget", + "cmd/go/internal/modinfo": "modinfo", + "cmd/go/internal/modload": "modload", + "cmd/go/internal/module": "module", + "cmd/go/internal/mvs": "mvs", + "cmd/go/internal/par": "par", + "cmd/go/internal/run": "run", + "cmd/go/internal/search": "search", + "cmd/go/internal/semver": "semver", + "cmd/go/internal/str": "str", + "cmd/go/internal/test": "test", + "cmd/go/internal/tool": "tool", + "cmd/go/internal/txtar": "txtar", + "cmd/go/internal/version": "version", + "cmd/go/internal/vet": "vet", + "cmd/go/internal/web": "web", + "cmd/go/internal/web2": "web2", + "cmd/go/internal/webtest": "webtest", + "cmd/go/internal/work": "work", + "cmd/internal/bio": "bio", + "cmd/internal/browser": "browser", + "cmd/internal/buildid": "buildid", + "cmd/internal/dwarf": "dwarf", + "cmd/internal/edit": "edit", + "cmd/internal/gcprog": "gcprog", + "cmd/internal/goobj": "goobj", + "cmd/internal/obj": "obj", + "cmd/internal/obj/arm": "arm", + "cmd/internal/obj/arm64": "arm64", + "cmd/internal/obj/mips": "mips", + "cmd/internal/obj/ppc64": "ppc64", + "cmd/internal/obj/s390x": "s390x", + "cmd/internal/obj/wasm": "wasm", + "cmd/internal/obj/x86": "x86", + "cmd/internal/objabi": "objabi", + "cmd/internal/objfile": "objfile", + "cmd/internal/src": "src", + "cmd/internal/sys": "sys", + "cmd/internal/test2json": "test2json", + "cmd/link/internal/amd64": "amd64", + "cmd/link/internal/arm": "arm", + "cmd/link/internal/arm64": "arm64", + "cmd/link/internal/ld": "ld", + "cmd/link/internal/loadelf": "loadelf", + "cmd/link/internal/loadmacho": "loadmacho", + "cmd/link/internal/loadpe": "loadpe", + "cmd/link/internal/mips": "mips", + "cmd/link/internal/mips64": "mips64", + "cmd/link/internal/objfile": "objfile", + "cmd/link/internal/ppc64": "ppc64", + "cmd/link/internal/s390x": "s390x", + "cmd/link/internal/sym": "sym", + "cmd/link/internal/wasm": "wasm", + "cmd/link/internal/x86": "x86", + "cmd/vet/internal/cfg": "cfg", + "cmd/vet/internal/whitelist": "whitelist", + "compress/bzip2": "bzip2", + "compress/flate": "flate", + "compress/gzip": "gzip", + "compress/lzw": "lzw", + "compress/zlib": "zlib", + "container/heap": "heap", + "container/list": "list", + "container/ring": "ring", + "context": "context", + "crypto": "crypto", + "crypto/aes": "aes", + "crypto/cipher": "cipher", + "crypto/des": "des", + "crypto/dsa": "dsa", + "crypto/ecdsa": "ecdsa", + "crypto/elliptic": "elliptic", + "crypto/hmac": "hmac", + "crypto/internal/randutil": "randutil", + "crypto/internal/subtle": "subtle", + "crypto/md5": "md5", + "crypto/rand": "rand", + "crypto/rc4": "rc4", + "crypto/rsa": "rsa", + "crypto/sha1": "sha1", + "crypto/sha256": "sha256", + "crypto/sha512": "sha512", + "crypto/subtle": "subtle", + "crypto/tls": "tls", + "crypto/x509": "x509", + "crypto/x509/pkix": "pkix", + "database/sql": "sql", + "database/sql/driver": "driver", + "debug/dwarf": "dwarf", + "debug/elf": "elf", + "debug/gosym": "gosym", + "debug/macho": "macho", + "debug/pe": "pe", + "debug/plan9obj": "plan9obj", + "encoding": "encoding", + "encoding/ascii85": "ascii85", + "encoding/asn1": "asn1", + "encoding/base32": "base32", + "encoding/base64": "base64", + "encoding/binary": "binary", + "encoding/csv": "csv", + "encoding/gob": "gob", + "encoding/hex": "hex", + "encoding/json": "json", + "encoding/pem": "pem", + "encoding/xml": "xml", + "errors": "errors", + "expvar": "expvar", + "flag": "flag", + "fmt": "fmt", + "go/ast": "ast", + "go/build": "build", + "go/constant": "constant", + "go/doc": "doc", + "go/format": "format", + "go/importer": "importer", + "go/internal/gccgoimporter": "gccgoimporter", + "go/internal/gcimporter": "gcimporter", + "go/internal/srcimporter": "srcimporter", + "go/parser": "parser", + "go/printer": "printer", + "go/scanner": "scanner", + "go/token": "token", + "go/types": "types", + "hash": "hash", + "hash/adler32": "adler32", + "hash/crc32": "crc32", + "hash/crc64": "crc64", + "hash/fnv": "fnv", + "html": "html", + "html/template": "template", + "image": "image", + "image/color": "color", + "image/color/palette": "palette", + "image/draw": "draw", + "image/gif": "gif", + "image/internal/imageutil": "imageutil", + "image/jpeg": "jpeg", + "image/png": "png", + "index/suffixarray": "suffixarray", + "internal/bytealg": "bytealg", + "internal/cpu": "cpu", + "internal/nettrace": "nettrace", + "internal/poll": "poll", + "internal/race": "race", + "internal/singleflight": "singleflight", + "internal/syscall/unix": "unix", + "internal/syscall/windows": "windows", + "internal/syscall/windows/registry": "registry", + "internal/syscall/windows/sysdll": "sysdll", + "internal/testenv": "testenv", + "internal/testlog": "testlog", + "internal/trace": "trace", + "io": "io", + "io/ioutil": "ioutil", + "log": "log", + "log/syslog": "syslog", + "math": "math", + "math/big": "big", + "math/bits": "bits", + "math/cmplx": "cmplx", + "math/rand": "rand", + "mime": "mime", + "mime/multipart": "multipart", + "mime/quotedprintable": "quotedprintable", + "net": "net", + "net/http": "http", + "net/http/cgi": "cgi", + "net/http/cookiejar": "cookiejar", + "net/http/fcgi": "fcgi", + "net/http/httptest": "httptest", + "net/http/httptrace": "httptrace", + "net/http/httputil": "httputil", + "net/http/internal": "internal", + "net/http/pprof": "pprof", + "net/internal/socktest": "socktest", + "net/mail": "mail", + "net/rpc": "rpc", + "net/rpc/jsonrpc": "jsonrpc", + "net/smtp": "smtp", + "net/textproto": "textproto", + "net/url": "url", + "os": "os", + "os/exec": "exec", + "os/signal": "signal", + "os/signal/internal/pty": "pty", + "os/user": "user", + "path": "path", + "path/filepath": "filepath", + "plugin": "plugin", + "reflect": "reflect", + "regexp": "regexp", + "regexp/syntax": "syntax", + "runtime": "runtime", + "runtime/cgo": "cgo", + "runtime/debug": "debug", + "runtime/internal/atomic": "atomic", + "runtime/internal/sys": "sys", + "runtime/pprof": "pprof", + "runtime/pprof/internal/profile": "profile", + "runtime/race": "race", + "runtime/trace": "trace", + "sort": "sort", + "strconv": "strconv", + "strings": "strings", + "sync": "sync", + "sync/atomic": "atomic", + "syscall": "syscall", + "testing": "testing", + "testing/internal/testdeps": "testdeps", + "testing/iotest": "iotest", + "testing/quick": "quick", + "text/scanner": "scanner", + "text/tabwriter": "tabwriter", + "text/template": "template", + "text/template/parse": "parse", + "time": "time", + "unicode": "unicode", + "unicode/utf16": "utf16", + "unicode/utf8": "utf8", + "unsafe": "unsafe", +} diff --git a/vendor/github.com/dave/jennifer/jen/jen.go b/vendor/github.com/dave/jennifer/jen/jen.go new file mode 100644 index 00000000..4cf480a1 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/jen.go @@ -0,0 +1,168 @@ +// Package jen is a code generator for Go +package jen + +import ( + "bytes" + "fmt" + "go/format" + "io" + "io/ioutil" + "sort" + "strconv" +) + +// Code represents an item of code that can be rendered. +type Code interface { + render(f *File, w io.Writer, s *Statement) error + isNull(f *File) bool +} + +// Save renders the file and saves to the filename provided. +func (f *File) Save(filename string) error { + // notest + buf := &bytes.Buffer{} + if err := f.Render(buf); err != nil { + return err + } + if err := ioutil.WriteFile(filename, buf.Bytes(), 0644); err != nil { + return err + } + return nil +} + +// Render renders the file to the provided writer. +func (f *File) Render(w io.Writer) error { + body := &bytes.Buffer{} + if err := f.render(f, body, nil); err != nil { + return err + } + source := &bytes.Buffer{} + if len(f.headers) > 0 { + for _, c := range f.headers { + if err := Comment(c).render(f, source, nil); err != nil { + return err + } + if _, err := fmt.Fprint(source, "\n"); err != nil { + return err + } + } + // Append an extra newline so that header comments don't get lumped in + // with package comments. + if _, err := fmt.Fprint(source, "\n"); err != nil { + return err + } + } + for _, c := range f.comments { + if err := Comment(c).render(f, source, nil); err != nil { + return err + } + if _, err := fmt.Fprint(source, "\n"); err != nil { + return err + } + } + if _, err := fmt.Fprintf(source, "package %s", f.name); err != nil { + return err + } + if f.CanonicalPath != "" { + if _, err := fmt.Fprintf(source, " // import %q", f.CanonicalPath); err != nil { + return err + } + } + if _, err := fmt.Fprint(source, "\n\n"); err != nil { + return err + } + if err := f.renderImports(source); err != nil { + return err + } + if _, err := source.Write(body.Bytes()); err != nil { + return err + } + formatted, err := format.Source(source.Bytes()) + if err != nil { + return fmt.Errorf("Error %s while formatting source:\n%s", err, source.String()) + } + if _, err := w.Write(formatted); err != nil { + return err + } + return nil +} + +func (f *File) renderImports(source io.Writer) error { + + // Render the "C" import if it's been used in a `Qual`, `Anon` or if there's a preamble comment + hasCgo := f.imports["C"].name != "" || len(f.cgoPreamble) > 0 + + // Only separate the import from the main imports block if there's a preamble + separateCgo := hasCgo && len(f.cgoPreamble) > 0 + + filtered := map[string]importdef{} + for path, def := range f.imports { + // filter out the "C" pseudo-package so it's not rendered in a block with the other + // imports, but only if it is accompanied by a preamble comment + if path == "C" && separateCgo { + continue + } + filtered[path] = def + } + + if len(filtered) == 1 { + for path, def := range filtered { + if def.alias && path != "C" { + // "C" package should be rendered without alias even when used as an anonymous import + // (e.g. should never have an underscore). + if _, err := fmt.Fprintf(source, "import %s %s\n\n", def.name, strconv.Quote(path)); err != nil { + return err + } + } else { + if _, err := fmt.Fprintf(source, "import %s\n\n", strconv.Quote(path)); err != nil { + return err + } + } + } + } else if len(filtered) > 1 { + if _, err := fmt.Fprint(source, "import (\n"); err != nil { + return err + } + // We must sort the imports to ensure repeatable + // source. + paths := []string{} + for path := range filtered { + paths = append(paths, path) + } + sort.Strings(paths) + for _, path := range paths { + def := filtered[path] + if def.alias && path != "C" { + // "C" package should be rendered without alias even when used as an anonymous import + // (e.g. should never have an underscore). + if _, err := fmt.Fprintf(source, "%s %s\n", def.name, strconv.Quote(path)); err != nil { + return err + } + + } else { + if _, err := fmt.Fprintf(source, "%s\n", strconv.Quote(path)); err != nil { + return err + } + } + } + if _, err := fmt.Fprint(source, ")\n\n"); err != nil { + return err + } + } + + if separateCgo { + for _, c := range f.cgoPreamble { + if err := Comment(c).render(f, source, nil); err != nil { + return err + } + if _, err := fmt.Fprint(source, "\n"); err != nil { + return err + } + } + if _, err := fmt.Fprint(source, "import \"C\"\n\n"); err != nil { + return err + } + } + + return nil +} diff --git a/vendor/github.com/dave/jennifer/jen/jen_test.go b/vendor/github.com/dave/jennifer/jen/jen_test.go new file mode 100644 index 00000000..ade18362 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/jen_test.go @@ -0,0 +1,550 @@ +package jen_test + +import ( + "fmt" + "go/format" + "strings" + "testing" + + . "github.com/dave/jennifer/jen" +) + +var o1 = Options{ + Close: ")", + Multi: true, + Open: "(", + Separator: ",", +} + +var o2 = Options{ + Close: "", + Multi: false, + Open: "", + Separator: ",", +} + +var cases = []tc{ + { + desc: `scientific notation`, + code: Lit(1e3), + expect: `1000.0`, + }, + { + desc: `big float`, + code: Lit(1000000.0), + expect: `1e+06`, + }, + { + desc: `lit float whole numbers`, + code: Index().Float64().Values(Lit(-10.0), Lit(-2.0), Lit(-1.0), Lit(0.0), Lit(1.0), Lit(2.0), Lit(10.0)), + expect: "[]float64{-10.0, -2.0, -1.0, 0.0, 1.0, 2.0, 10.0}", + }, + { + desc: `custom func group`, + code: ListFunc(func(g *Group) { + g.CustomFunc(o2, func(g *Group) { + g.Id("a") + g.Id("b") + g.Id("c") + }) + }).Op("=").Id("foo").Call(), + expect: `a, b, c = foo()`, + }, + { + desc: `custom group`, + code: ListFunc(func(g *Group) { g.Custom(o2, Id("a"), Id("b"), Id("c")) }).Op("=").Id("foo").Call(), + expect: `a, b, c = foo()`, + }, + { + desc: `custom function`, + code: Id("foo").Add(Custom(o1, Lit("a"), Lit("b"), Lit("c"))), + expect: `foo( + "a", + "b", + "c", + )`, + }, + { + desc: `custom function`, + code: Id("foo").Add(Custom(o1, Lit("a"), Lit("b"), Lit("c"))), + expect: `foo( + "a", + "b", + "c", + )`, + }, + { + desc: `line statement`, + code: Block(Lit(1).Line(), Lit(2)), + expect: `{ + 1 + + 2 + }`, + }, + { + desc: `line func`, + code: Block(Lit(1), Line(), Lit(2)), + expect: `{ + 1 + + 2 + }`, + }, + { + desc: `line group`, + code: BlockFunc(func(g *Group) { + g.Id("a") + g.Line() + g.Id("b") + }), + expect: `{ + a + + b + }`, + }, + { + desc: `op group`, + code: BlockFunc(func(g *Group) { + g.Op("*").Id("a") + }), + expect: `{*a}`, + }, + { + desc: `empty group`, + code: BlockFunc(func(g *Group) { + g.Empty() + }), + expect: `{ + + }`, + }, + { + desc: `null group`, + code: BlockFunc(func(g *Group) { + g.Null() + }), + expect: `{}`, + }, + { + desc: `tag no backquote`, + code: Tag(map[string]string{"a": "`b`"}), + expect: "\"a:\\\"`b`\\\"\"", + }, + { + desc: `tag null`, + code: Tag(map[string]string{}), + expect: ``, + }, + { + desc: `litrunefunc group`, + code: BlockFunc(func(g *Group) { + g.LitByteFunc(func() byte { return byte(0xab) }) + }), + expect: `{byte(0xab)}`, + }, + { + desc: `litbyte group`, + code: BlockFunc(func(g *Group) { + g.LitByte(byte(0xab)) + }), + expect: `{byte(0xab)}`, + }, + { + desc: `litrunefunc group`, + code: BlockFunc(func(g *Group) { + g.LitRuneFunc(func() rune { return 'a' }) + }), + expect: `{'a'}`, + }, + { + desc: `litrune group`, + code: BlockFunc(func(g *Group) { + g.LitRune('a') + }), + expect: `{'a'}`, + }, + { + desc: `litfunc group`, + code: BlockFunc(func(g *Group) { + g.LitFunc(func() interface{} { + return 1 + 1 + }) + }), + expect: `{2}`, + }, + { + desc: `litfunc func`, + code: LitFunc(func() interface{} { + return 1 + 1 + }), + expect: `2`, + }, + { + desc: `group all null`, + code: List(Null(), Null()), + expect: ``, + }, + { + desc: `do group`, + code: BlockFunc(func(g *Group) { g.Do(func(s *Statement) { s.Lit(1) }) }), + expect: `{1}`, + }, + { + desc: `do func`, + code: Do(func(s *Statement) { s.Lit(1) }), + expect: `1`, + }, + { + desc: `dict empty`, + code: Values(Dict{}), + expect: `{}`, + }, + { + desc: `dict null`, + code: Values(Dict{Null(): Null()}), + expect: `{}`, + }, + { + desc: `commentf group`, + code: BlockFunc(func(g *Group) { g.Commentf("%d", 1) }), + expect: `{ + // 1 + }`, + }, + { + desc: `commentf func`, + code: Commentf("%d", 1), + expect: `// 1`, + }, + { + desc: `add func`, + code: Add(Lit(1)), + expect: `1`, + }, + { + desc: `add group`, + code: BlockFunc(func(g *Group) { g.Add(Lit(1)) }), + expect: `{1}`, + }, + { + desc: `empty block`, + code: Block(), + expect: `{}`, + }, + { + desc: `string literal`, + code: Lit("a"), + expect: `"a"`, + }, + { + desc: `int literal`, + code: Lit(1), + expect: `1`, + }, + { + desc: `simple id`, + code: Id("a"), + expect: `a`, + }, + { + desc: `foreign id`, + code: Qual("x.y/z", "a"), + expect: `z.a`, + expectImports: map[string]string{ + "x.y/z": "z", + }, + }, + { + desc: `var decl`, + code: Var().Id("a").Op("=").Lit("b"), + expect: `var a = "b"`, + }, + { + desc: `short var decl`, + code: Id("a").Op(":=").Lit("b"), + expect: `a := "b"`, + }, + { + desc: `simple if`, + code: If(Id("a").Op("==").Lit("b")).Block(), + expect: `if a == "b" {}`, + }, + { + desc: `simple if`, + code: If(Id("a").Op("==").Lit("b")).Block( + Id("a").Op("++"), + ), + expect: `if a == "b" { a++ }`, + }, + { + desc: `pointer`, + code: Op("*").Id("a"), + expect: `*a`, + }, + { + desc: `address`, + code: Op("&").Id("a"), + expect: `&a`, + }, + { + desc: `simple call`, + code: Id("a").Call( + Lit("b"), + Lit("c"), + ), + expect: `a("b", "c")`, + }, + { + desc: `call fmt.Sprintf`, + code: Qual("fmt", "Sprintf").Call( + Lit("b"), + Id("c"), + ), + expect: `fmt.Sprintf("b", c)`, + }, + { + desc: `slices`, + code: Id("a").Index( + Lit(1), + Empty(), + ), + expect: `a[1:]`, + }, + { + desc: `return`, + code: Return(Id("a")), + expect: `return a`, + }, + { + desc: `double return`, + code: Return(Id("a"), Id("b")), + expect: `return a, b`, + }, + { + desc: `func`, + code: Func().Id("a").Params( + Id("a").String(), + ).Block( + Return(Id("a")), + ), + expect: `func a(a string){ + return a + }`, + }, + { + desc: `built in func`, + code: New(Id("a")), + expect: `new(a)`, + }, + { + desc: `multip`, + code: Id("a").Op("*").Id("b"), + expect: `a * b`, + }, + { + desc: `multip ptr`, + code: Id("a").Op("*").Op("*").Id("b"), + expect: `a * *b`, + }, + { + desc: `field`, + code: Id("a").Dot("b"), + expect: `a.b`, + }, + { + desc: `method`, + code: Id("a").Dot("b").Call(Id("c"), Id("d")), + expect: `a.b(c, d)`, + }, + { + desc: `if else`, + code: If(Id("a").Op("==").Lit(1)).Block( + Id("b").Op("=").Lit(1), + ).Else().If(Id("a").Op("==").Lit(2)).Block( + Id("b").Op("=").Lit(2), + ).Else().Block( + Id("b").Op("=").Lit(3), + ), + expect: `if a == 1 { b = 1 } else if a == 2 { b = 2 } else { b = 3 }`, + }, + { + desc: `literal array`, + code: Index().String().Values(Lit("a"), Lit("b")), + expect: `[]string{"a", "b"}`, + }, + { + desc: `comment`, + code: Comment("a"), + expect: `// a`, + }, + { + desc: `null`, + code: Id("a").Params(Id("b"), Null(), Id("c")), + expect: `a(b, c)`, + }, + { + desc: `map literal single`, + code: Id("a").Values(Dict{ + Id("b"): Id("c"), + }), + expect: `a{b: c}`, + }, + { + desc: `map literal null`, + code: Id("a").Values(Dict{ + Null(): Id("c"), + Id("b"): Null(), + Id("b"): Id("c"), + }), + expect: `a{b: c}`, + }, + { + desc: `map literal multiple`, + code: Id("a").Values(Dict{ + Id("b"): Id("c"), + Id("d"): Id("e"), + }), + expect: `a{ + b: c, + d: e, + }`, + }, + { + desc: `map literal func single`, + code: Id("a").Values(DictFunc(func(d Dict) { + d[Id("b")] = Id("c") + })), + expect: `a{b: c}`, + }, + { + desc: `map literal func single null`, + code: Id("a").Values(DictFunc(func(d Dict) { + d[Null()] = Id("c") + d[Id("b")] = Null() + d[Id("b")] = Id("c") + })), + expect: `a{b: c}`, + }, + { + desc: `map literal func multiple`, + code: Id("a").Values(DictFunc(func(d Dict) { + d[Id("b")] = Id("c") + d[Id("d")] = Id("e") + })), + expect: `a{ + b: c, + d: e, + }`, + }, + { + desc: `literal func`, + code: Id("a").Op(":=").LitFunc(func() interface{} { + return "b" + }), + expect: `a := "b"`, + }, + { + desc: `dot`, + code: Id("a").Dot("b").Dot("c"), + expect: `a.b.c`, + }, + { + desc: `do`, + code: Id("a").Do(func(s *Statement) { s.Dot("b") }), + expect: `a.b`, + }, + { + desc: `tags should be ordered`, + code: Tag(map[string]string{"z": "1", "a": "2"}), + expect: "`a:\"2\" z:\"1\"`", + }, + { + desc: `dict should be ordered`, + code: Map(String()).Int().Values(Dict{Id("z"): Lit(1), Id("a"): Lit(2)}), + expect: `map[string]int{ + a:2, + z:1, + }`, + }, +} + +func TestJen(t *testing.T) { + caseTester(t, cases) +} + +func caseTester(t *testing.T, cases []tc) { + for i, c := range cases { + onlyTest := "" + if onlyTest != "" && c.desc != onlyTest { + continue + } + rendered := fmt.Sprintf("%#v", c.code) + + expected, err := format.Source([]byte(c.expect)) + if err != nil { + panic(fmt.Sprintf("Error formatting expected source in test case %d. Description: %s\nError:\n%s", i, c.desc, err)) + } + + if strings.TrimSpace(string(rendered)) != strings.TrimSpace(string(expected)) { + t.Errorf("Test case %d failed. Description: %s\nExpected:\n%s\nOutput:\n%s", i, c.desc, expected, rendered) + } + + //if c.expectImports != nil { + // f := FromContext(ctx) + // if !reflect.DeepEqual(f.Imports, c.expectImports) { + // t.Errorf("Test case %d failed. Description: %s\nImports expected:\n%s\nOutput:\n%s", i, c.desc, c.expectImports, f.Imports) + // } + //} + } +} + +// a test case +type tc struct { + // path + path string + // description for locating the test case + desc string + // code to generate + code Code + // expected generated source + expect string + // expected imports + expectImports map[string]string +} + +func TestNilStatement(t *testing.T) { + var s *Statement + c := Func().Id("a").Params( + s, + ) + got := fmt.Sprintf("%#v", c) + expect := "func a()" + if got != expect { + t.Fatalf("Got: %s, expect: %s", got, expect) + } +} + +func TestNilGroup(t *testing.T) { + var g *Group + c := Func().Id("a").Params( + g, + ) + got := fmt.Sprintf("%#v", c) + expect := "func a()" + if got != expect { + t.Fatalf("Got: %s, expect: %s", got, expect) + } +} + +func TestGroup_GoString(t *testing.T) { + BlockFunc(func(g *Group) { + g.Lit(1) + got := fmt.Sprintf("%#v", g) + expect := "{\n\t1\n}" + if got != expect { + t.Fatalf("Got: %s, expect: %s", got, expect) + } + }) +} diff --git a/vendor/github.com/dave/jennifer/jen/lit.go b/vendor/github.com/dave/jennifer/jen/lit.go new file mode 100644 index 00000000..9791f1d2 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/lit.go @@ -0,0 +1,154 @@ +package jen + +// Lit renders a literal. Lit supports only built-in types (bool, string, int, complex128, float64, +// float32, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr and complex64). +// Passing any other type will panic. +func Lit(v interface{}) *Statement { + return newStatement().Lit(v) +} + +// Lit renders a literal. Lit supports only built-in types (bool, string, int, complex128, float64, +// float32, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr and complex64). +// Passing any other type will panic. +func (g *Group) Lit(v interface{}) *Statement { + s := Lit(v) + g.items = append(g.items, s) + return s +} + +// Lit renders a literal. Lit supports only built-in types (bool, string, int, complex128, float64, +// float32, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr and complex64). +// Passing any other type will panic. +func (s *Statement) Lit(v interface{}) *Statement { + t := token{ + typ: literalToken, + content: v, + } + *s = append(*s, t) + return s +} + +// LitFunc renders a literal. LitFunc generates the value to render by executing the provided +// function. LitFunc supports only built-in types (bool, string, int, complex128, float64, float32, +// int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr and complex64). +// Returning any other type will panic. +func LitFunc(f func() interface{}) *Statement { + return newStatement().LitFunc(f) +} + +// LitFunc renders a literal. LitFunc generates the value to render by executing the provided +// function. LitFunc supports only built-in types (bool, string, int, complex128, float64, float32, +// int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr and complex64). +// Returning any other type will panic. +func (g *Group) LitFunc(f func() interface{}) *Statement { + s := LitFunc(f) + g.items = append(g.items, s) + return s +} + +// LitFunc renders a literal. LitFunc generates the value to render by executing the provided +// function. LitFunc supports only built-in types (bool, string, int, complex128, float64, float32, +// int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr and complex64). +// Returning any other type will panic. +func (s *Statement) LitFunc(f func() interface{}) *Statement { + t := token{ + typ: literalToken, + content: f(), + } + *s = append(*s, t) + return s +} + +// LitRune renders a rune literal. +func LitRune(v rune) *Statement { + return newStatement().LitRune(v) +} + +// LitRune renders a rune literal. +func (g *Group) LitRune(v rune) *Statement { + s := LitRune(v) + g.items = append(g.items, s) + return s +} + +// LitRune renders a rune literal. +func (s *Statement) LitRune(v rune) *Statement { + t := token{ + typ: literalRuneToken, + content: v, + } + *s = append(*s, t) + return s +} + +// LitRuneFunc renders a rune literal. LitRuneFunc generates the value to +// render by executing the provided function. +func LitRuneFunc(f func() rune) *Statement { + return newStatement().LitRuneFunc(f) +} + +// LitRuneFunc renders a rune literal. LitRuneFunc generates the value to +// render by executing the provided function. +func (g *Group) LitRuneFunc(f func() rune) *Statement { + s := LitRuneFunc(f) + g.items = append(g.items, s) + return s +} + +// LitRuneFunc renders a rune literal. LitRuneFunc generates the value to +// render by executing the provided function. +func (s *Statement) LitRuneFunc(f func() rune) *Statement { + t := token{ + typ: literalRuneToken, + content: f(), + } + *s = append(*s, t) + return s +} + +// LitByte renders a byte literal. +func LitByte(v byte) *Statement { + return newStatement().LitByte(v) +} + +// LitByte renders a byte literal. +func (g *Group) LitByte(v byte) *Statement { + s := LitByte(v) + g.items = append(g.items, s) + return s +} + +// LitByte renders a byte literal. +func (s *Statement) LitByte(v byte) *Statement { + t := token{ + typ: literalByteToken, + content: v, + } + *s = append(*s, t) + return s +} + +// LitByteFunc renders a byte literal. LitByteFunc generates the value to +// render by executing the provided function. +func LitByteFunc(f func() byte) *Statement { + return newStatement().LitByteFunc(f) +} + +// LitByteFunc renders a byte literal. LitByteFunc generates the value to +// render by executing the provided function. +func (g *Group) LitByteFunc(f func() byte) *Statement { + s := LitByteFunc(f) + g.items = append(g.items, s) + return s +} + +// LitByteFunc renders a byte literal. LitByteFunc generates the value to +// render by executing the provided function. +func (s *Statement) LitByteFunc(f func() byte) *Statement { + t := token{ + typ: literalByteToken, + content: f(), + } + *s = append(*s, t) + return s +} diff --git a/vendor/github.com/dave/jennifer/jen/statement.go b/vendor/github.com/dave/jennifer/jen/statement.go new file mode 100644 index 00000000..aa9ec497 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/statement.go @@ -0,0 +1,101 @@ +package jen + +import ( + "bytes" + "fmt" + "go/format" + "io" +) + +// Statement represents a simple list of code items. When rendered the items +// are separated by spaces. +type Statement []Code + +func newStatement() *Statement { + return &Statement{} +} + +// Clone makes a copy of the Statement, so further tokens can be appended +// without affecting the original. +func (s *Statement) Clone() *Statement { + return &Statement{s} +} + +func (s *Statement) previous(c Code) Code { + index := -1 + for i, item := range *s { + if item == c { + index = i + break + } + } + if index > 0 { + return (*s)[index-1] + } + return nil +} + +func (s *Statement) isNull(f *File) bool { + if s == nil { + return true + } + for _, c := range *s { + if !c.isNull(f) { + return false + } + } + return true +} + +func (s *Statement) render(f *File, w io.Writer, _ *Statement) error { + first := true + for _, code := range *s { + if code == nil || code.isNull(f) { + // Null() token produces no output but also + // no separator. Empty() token products no + // output but adds a separator. + continue + } + if !first { + if _, err := w.Write([]byte(" ")); err != nil { + return err + } + } + if err := code.render(f, w, s); err != nil { + return err + } + first = false + } + return nil +} + +// Render renders the Statement to the provided writer. +func (s *Statement) Render(writer io.Writer) error { + return s.RenderWithFile(writer, NewFile("")) +} + +// GoString renders the Statement for testing. Any error will cause a panic. +func (s *Statement) GoString() string { + buf := bytes.Buffer{} + if err := s.Render(&buf); err != nil { + panic(err) + } + return buf.String() +} + +// RenderWithFile renders the Statement to the provided writer, using imports from the provided file. +func (s *Statement) RenderWithFile(writer io.Writer, file *File) error { + buf := &bytes.Buffer{} + if err := s.render(file, buf, nil); err != nil { + return err + } + b, err := format.Source(buf.Bytes()) + if err != nil { + return fmt.Errorf("Error %s while formatting source:\n%s", err, buf.String()) + } + if _, err := writer.Write(b); err != nil { + return err + } + return nil +} + diff --git a/vendor/github.com/dave/jennifer/jen/statement_test.go b/vendor/github.com/dave/jennifer/jen/statement_test.go new file mode 100644 index 00000000..d774f6e9 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/statement_test.go @@ -0,0 +1,32 @@ +package jen_test + +import ( + "bytes" + "testing" + + . "github.com/dave/jennifer/jen" +) + +func TestStatement_Render(t *testing.T) { + file := NewFile("main") + file.ImportAlias("fmt", "fmtalias") + + statement := file.Func().Id("main").Params().Block( + Qual("fmt", "Println").Call(Lit("something")), + ) + + expect := `func main() { + fmtalias.Println("something") +}` + + var got bytes.Buffer + + err := statement.RenderWithFile(&got, file) + if err != nil { + t.Fatal(err) + } + + if got.String() != expect { + t.Fatalf("Got: %v, expect: %v", got.String(), expect) + } +} diff --git a/vendor/github.com/dave/jennifer/jen/tag.go b/vendor/github.com/dave/jennifer/jen/tag.go new file mode 100644 index 00000000..ad99aafd --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/tag.go @@ -0,0 +1,76 @@ +package jen + +import ( + "fmt" + "io" + "sort" + "strconv" +) + +// Tag renders a struct tag +func Tag(items map[string]string) *Statement { + return newStatement().Tag(items) +} + +// Tag renders a struct tag +func (g *Group) Tag(items map[string]string) *Statement { + // notest + // don't think this can ever be used in valid code? + s := Tag(items) + g.items = append(g.items, s) + return s +} + +// Tag renders a struct tag +func (s *Statement) Tag(items map[string]string) *Statement { + c := tag{ + items: items, + } + *s = append(*s, c) + return s +} + +type tag struct { + items map[string]string +} + +func (t tag) isNull(f *File) bool { + return len(t.items) == 0 +} + +func (t tag) render(f *File, w io.Writer, s *Statement) error { + + if t.isNull(f) { + // notest + // render won't be called if t is null + return nil + } + + var str string + + var sorted []string + for k := range t.items { + sorted = append(sorted, k) + } + sort.Strings(sorted) + + for _, k := range sorted { + v := t.items[k] + if len(str) > 0 { + str += " " + } + str += fmt.Sprintf(`%s:"%s"`, k, v) + } + + if strconv.CanBackquote(str) { + str = "`" + str + "`" + } else { + str = strconv.Quote(str) + } + + if _, err := w.Write([]byte(str)); err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/dave/jennifer/jen/tokens.go b/vendor/github.com/dave/jennifer/jen/tokens.go new file mode 100644 index 00000000..287a3cd6 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jen/tokens.go @@ -0,0 +1,301 @@ +package jen + +import ( + "fmt" + "io" + "strconv" + "strings" +) + +type tokenType string + +const ( + packageToken tokenType = "package" + identifierToken tokenType = "identifier" + qualifiedToken tokenType = "qualified" + keywordToken tokenType = "keyword" + operatorToken tokenType = "operator" + delimiterToken tokenType = "delimiter" + literalToken tokenType = "literal" + literalRuneToken tokenType = "literal_rune" + literalByteToken tokenType = "literal_byte" + nullToken tokenType = "null" + layoutToken tokenType = "layout" +) + +type token struct { + typ tokenType + content interface{} +} + +func (t token) isNull(f *File) bool { + if t.typ == packageToken { + // package token is null if the path is a dot-import or the local package path + return f.isDotImport(t.content.(string)) || f.isLocal(t.content.(string)) + } + return t.typ == nullToken +} + +func (t token) render(f *File, w io.Writer, s *Statement) error { + switch t.typ { + case literalToken: + var out string + switch t.content.(type) { + case bool, string, int, complex128: + // default constant types can be left bare + out = fmt.Sprintf("%#v", t.content) + case float64: + out = fmt.Sprintf("%#v", t.content) + if !strings.Contains(out, ".") && !strings.Contains(out, "e") { + // If the formatted value is not in scientific notation, and does not have a dot, then + // we add ".0". Otherwise it will be interpreted as an int. + // See: + // https://github.com/dave/jennifer/issues/39 + // https://github.com/golang/go/issues/26363 + out += ".0" + } + case float32, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr: + // other built-in types need specific type info + out = fmt.Sprintf("%T(%#v)", t.content, t.content) + case complex64: + // fmt package already renders parenthesis for complex64 + out = fmt.Sprintf("%T%#v", t.content, t.content) + default: + panic(fmt.Sprintf("unsupported type for literal: %T", t.content)) + } + if _, err := w.Write([]byte(out)); err != nil { + return err + } + case literalRuneToken: + if _, err := w.Write([]byte(strconv.QuoteRune(t.content.(rune)))); err != nil { + return err + } + case literalByteToken: + if _, err := w.Write([]byte(fmt.Sprintf("byte(%#v)", t.content))); err != nil { + return err + } + case keywordToken, operatorToken, layoutToken, delimiterToken: + if _, err := w.Write([]byte(fmt.Sprintf("%s", t.content))); err != nil { + return err + } + if t.content.(string) == "default" { + // Special case for Default, which must always be followed by a colon + if _, err := w.Write([]byte(":")); err != nil { + return err + } + } + case packageToken: + path := t.content.(string) + alias := f.register(path) + if _, err := w.Write([]byte(alias)); err != nil { + return err + } + case identifierToken: + if _, err := w.Write([]byte(t.content.(string))); err != nil { + return err + } + case nullToken: // notest + // do nothing (should never render a null token) + } + return nil +} + +// Null adds a null item. Null items render nothing and are not followed by a +// separator in lists. +func Null() *Statement { + return newStatement().Null() +} + +// Null adds a null item. Null items render nothing and are not followed by a +// separator in lists. +func (g *Group) Null() *Statement { + s := Null() + g.items = append(g.items, s) + return s +} + +// Null adds a null item. Null items render nothing and are not followed by a +// separator in lists. +func (s *Statement) Null() *Statement { + t := token{ + typ: nullToken, + } + *s = append(*s, t) + return s +} + +// Empty adds an empty item. Empty items render nothing but are followed by a +// separator in lists. +func Empty() *Statement { + return newStatement().Empty() +} + +// Empty adds an empty item. Empty items render nothing but are followed by a +// separator in lists. +func (g *Group) Empty() *Statement { + s := Empty() + g.items = append(g.items, s) + return s +} + +// Empty adds an empty item. Empty items render nothing but are followed by a +// separator in lists. +func (s *Statement) Empty() *Statement { + t := token{ + typ: operatorToken, + content: "", + } + *s = append(*s, t) + return s +} + +// Op renders the provided operator / token. +func Op(op string) *Statement { + return newStatement().Op(op) +} + +// Op renders the provided operator / token. +func (g *Group) Op(op string) *Statement { + s := Op(op) + g.items = append(g.items, s) + return s +} + +// Op renders the provided operator / token. +func (s *Statement) Op(op string) *Statement { + t := token{ + typ: operatorToken, + content: op, + } + *s = append(*s, t) + return s +} + +// Dot renders a period followed by an identifier. Use for fields and selectors. +func Dot(name string) *Statement { + // notest + // don't think this can be used in valid code? + return newStatement().Dot(name) +} + +// Dot renders a period followed by an identifier. Use for fields and selectors. +func (g *Group) Dot(name string) *Statement { + // notest + // don't think this can be used in valid code? + s := Dot(name) + g.items = append(g.items, s) + return s +} + +// Dot renders a period followed by an identifier. Use for fields and selectors. +func (s *Statement) Dot(name string) *Statement { + d := token{ + typ: delimiterToken, + content: ".", + } + t := token{ + typ: identifierToken, + content: name, + } + *s = append(*s, d, t) + return s +} + +// Id renders an identifier. +func Id(name string) *Statement { + return newStatement().Id(name) +} + +// Id renders an identifier. +func (g *Group) Id(name string) *Statement { + s := Id(name) + g.items = append(g.items, s) + return s +} + +// Id renders an identifier. +func (s *Statement) Id(name string) *Statement { + t := token{ + typ: identifierToken, + content: name, + } + *s = append(*s, t) + return s +} + +// Qual renders a qualified identifier. Imports are automatically added when +// used with a File. If the path matches the local path, the package name is +// omitted. If package names conflict they are automatically renamed. Note that +// it is not possible to reliably determine the package name given an arbitrary +// package path, so a sensible name is guessed from the path and added as an +// alias. The names of all standard library packages are known so these do not +// need to be aliased. If more control is needed of the aliases, see +// [File.ImportName](#importname) or [File.ImportAlias](#importalias). +func Qual(path, name string) *Statement { + return newStatement().Qual(path, name) +} + +// Qual renders a qualified identifier. Imports are automatically added when +// used with a File. If the path matches the local path, the package name is +// omitted. If package names conflict they are automatically renamed. Note that +// it is not possible to reliably determine the package name given an arbitrary +// package path, so a sensible name is guessed from the path and added as an +// alias. The names of all standard library packages are known so these do not +// need to be aliased. If more control is needed of the aliases, see +// [File.ImportName](#importname) or [File.ImportAlias](#importalias). +func (g *Group) Qual(path, name string) *Statement { + s := Qual(path, name) + g.items = append(g.items, s) + return s +} + +// Qual renders a qualified identifier. Imports are automatically added when +// used with a File. If the path matches the local path, the package name is +// omitted. If package names conflict they are automatically renamed. Note that +// it is not possible to reliably determine the package name given an arbitrary +// package path, so a sensible name is guessed from the path and added as an +// alias. The names of all standard library packages are known so these do not +// need to be aliased. If more control is needed of the aliases, see +// [File.ImportName](#importname) or [File.ImportAlias](#importalias). +func (s *Statement) Qual(path, name string) *Statement { + g := &Group{ + close: "", + items: []Code{ + token{ + typ: packageToken, + content: path, + }, + token{ + typ: identifierToken, + content: name, + }, + }, + name: "qual", + open: "", + separator: ".", + } + *s = append(*s, g) + return s +} + +// Line inserts a blank line. +func Line() *Statement { + return newStatement().Line() +} + +// Line inserts a blank line. +func (g *Group) Line() *Statement { + s := Line() + g.items = append(g.items, s) + return s +} + +// Line inserts a blank line. +func (s *Statement) Line() *Statement { + t := token{ + typ: layoutToken, + content: "\n", + } + *s = append(*s, t) + return s +} diff --git a/vendor/github.com/dave/jennifer/jennifer.go b/vendor/github.com/dave/jennifer/jennifer.go new file mode 100644 index 00000000..37efad44 --- /dev/null +++ b/vendor/github.com/dave/jennifer/jennifer.go @@ -0,0 +1,9 @@ +// Package jennifer is a code generator for Go +package jennifer + +//go:generate go get github.com/dave/jennifer/genjen +//go:generate genjen +//go:generate go get github.com/dave/jennifer/gennames +//go:generate gennames -output "jen/hints.go" -package "jen" -name "standardLibraryHints" -standard -novendor -path "./..." +//go:generate go get github.com/dave/rebecca/cmd/becca +//go:generate becca -package=github.com/dave/jennifer/jen