From 2d37d3321b38993b56daeb131dba33eda3cdd0ea Mon Sep 17 00:00:00 2001 From: Anton Sviridov Date: Tue, 2 May 2023 10:37:04 +0100 Subject: [PATCH 1/9] json subcommand --- cmd/json.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++ cmd/main.go | 3 ++- 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 cmd/json.go diff --git a/cmd/json.go b/cmd/json.go new file mode 100644 index 00000000..976a57a0 --- /dev/null +++ b/cmd/json.go @@ -0,0 +1,59 @@ +package main + +import ( + "fmt" + + "github.com/sourcegraph/sourcegraph/lib/errors" + "github.com/urfave/cli/v2" + "google.golang.org/protobuf/encoding/protojson" +) + +type jsonFlags struct { + from string + pretty bool +} + +func jsonCommand() cli.Command { + var jsonFlags jsonFlags + + json := cli.Command{ + Name: "json", + Usage: "Print SCIP index as json", + Flags: []cli.Flag{ + fromFlag(&jsonFlags.from), + &cli.BoolFlag{ + Name: "pretty", + Usage: "Pretty print", + Aliases: []string{"p"}, + Destination: &jsonFlags.pretty, + }, + }, + Action: func(c *cli.Context) error { + if jsonFlags.from == "" { + return errors.New("missing argument for path to SCIP index") + } + return jsonMain(jsonFlags) + }, + } + + return json +} + +func jsonMain(flags jsonFlags) error { + + fmt.Println(flags) + + scipIndex, err := readFromOption(flags.from) + if err != nil { + return err + } + + options := protojson.MarshalOptions{ + Multiline: flags.pretty, + } + + jsonBytes, _ := options.Marshal(scipIndex) + fmt.Println(string(jsonBytes)) + + return nil +} diff --git a/cmd/main.go b/cmd/main.go index 986e8fdc..c0f80080 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -24,7 +24,8 @@ func commands() []*cli.Command { print := printCommand() snapshot := snapshotCommand() stats := statsCommand() - return []*cli.Command{&convert, &lint, &print, &snapshot, &stats} + json := jsonCommand() + return []*cli.Command{&convert, &lint, &print, &snapshot, &stats, &json} } //go:embed version.txt From 07217413dae323dc8a00ac0f6d20baca244bd72f Mon Sep 17 00:00:00 2001 From: Anton Sviridov Date: Tue, 2 May 2023 10:44:18 +0100 Subject: [PATCH 2/9] Update docs --- cmd/json.go | 4 ++-- docs/CLI.md | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/cmd/json.go b/cmd/json.go index 976a57a0..952fa89d 100644 --- a/cmd/json.go +++ b/cmd/json.go @@ -18,12 +18,12 @@ func jsonCommand() cli.Command { json := cli.Command{ Name: "json", - Usage: "Print SCIP index as json", + Usage: "Print SCIP index as JSON", Flags: []cli.Flag{ fromFlag(&jsonFlags.from), &cli.BoolFlag{ Name: "pretty", - Usage: "Pretty print", + Usage: "Pretty print (multiline, with indentation)", Aliases: []string{"p"}, Destination: &jsonFlags.pretty, }, diff --git a/docs/CLI.md b/docs/CLI.md index 9ec3f8fb..285494bc 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -1,5 +1,15 @@ # SCIP CLI Reference + +- [SCIP CLI Reference](#scip-cli-reference) + - [`scip convert`](#scip-convert) + - [`scip lint`](#scip-lint) + - [`scip print`](#scip-print) + - [`scip snapshot`](#scip-snapshot) + - [`scip stats`](#scip-stats) + - [`scip json`](#scip-json) + + ``` NAME: scip - SCIP Code Intelligence Protocol CLI @@ -21,6 +31,7 @@ COMMANDS: print Print a SCIP index in a human-readable format for debugging snapshot Generate snapshot files for golden testing stats Output useful statistics about a SCIP index + json Print SCIP index as JSON help, h Shows a list of commands or help for one command GLOBAL OPTIONS: @@ -96,8 +107,12 @@ DESCRIPTION: and symbol information. OPTIONS: - --from value Path to SCIP index file (default: index.scip) - --to value Path to output directory for snapshot files (default: scip-snapshot) + --comment-syntax value Comment syntax to use for snapshot files (default: "//") + --from value Path to SCIP index file (default: "index.scip") + --help, -h show help (default: false) + --project-root value Override project root in the SCIP file. For example, this can be helpful when the SCIP index was created inside a Docker image or created on another computer + --strict If true, fail fast on errors (default: true) + --to value Path to output directory for snapshot files (default: "scip-snapshot") ``` ## `scip stats` @@ -112,3 +127,20 @@ USAGE: OPTIONS: --from value Path to SCIP index file (default: index.scip) ``` + +## `scip json` + +``` +NAME: + scip json - Print SCIP index as JSON + +USAGE: + scip json [command options] [arguments...] + +OPTIONS: + --from value Path to SCIP index file (default: "index.scip") + --help, -h show help (default: false) + --pretty, -p Pretty print (multiline, with indentation) (default: false) +``` + + From 1b8d465681b29b7712e008188834489a2d8dc4bc Mon Sep 17 00:00:00 2001 From: Anton Sviridov Date: Tue, 2 May 2023 11:07:44 +0100 Subject: [PATCH 3/9] Formatting --- cmd/convert.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/convert.go b/cmd/convert.go index f3007171..0c4f9414 100644 --- a/cmd/convert.go +++ b/cmd/convert.go @@ -29,7 +29,7 @@ func convertCommand() cli.Command { Name: "to", Usage: "Output path for LSIF index", Destination: &convertFlags.to, - Value: "dump.lsif", + Value: "dump.lsif", }, }, Action: func(c *cli.Context) error { From 796df20a2ce2e0202e34ba1086dd06db36502fce Mon Sep 17 00:00:00 2001 From: Anton Sviridov Date: Tue, 2 May 2023 11:10:28 +0100 Subject: [PATCH 4/9] urgh markdown formatting --- docs/CLI.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/CLI.md b/docs/CLI.md index 285494bc..4683db46 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -1,6 +1,7 @@ # SCIP CLI Reference + - [SCIP CLI Reference](#scip-cli-reference) - [`scip convert`](#scip-convert) - [`scip lint`](#scip-lint) @@ -8,7 +9,7 @@ - [`scip snapshot`](#scip-snapshot) - [`scip stats`](#scip-stats) - [`scip json`](#scip-json) - + ``` NAME: @@ -142,5 +143,3 @@ OPTIONS: --help, -h show help (default: false) --pretty, -p Pretty print (multiline, with indentation) (default: false) ``` - - From aece669d1ce6c843c871b4a10eb1df6d28a954f0 Mon Sep 17 00:00:00 2001 From: Anton Sviridov Date: Tue, 2 May 2023 13:59:48 +0100 Subject: [PATCH 5/9] Add end-to-end tests for json subcommand --- cmd/json.go | 7 ++--- cmd/json_test.go | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 cmd/json_test.go diff --git a/cmd/json.go b/cmd/json.go index 952fa89d..0b27f558 100644 --- a/cmd/json.go +++ b/cmd/json.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "io" "github.com/sourcegraph/sourcegraph/lib/errors" "github.com/urfave/cli/v2" @@ -32,14 +33,14 @@ func jsonCommand() cli.Command { if jsonFlags.from == "" { return errors.New("missing argument for path to SCIP index") } - return jsonMain(jsonFlags) + return jsonMain(jsonFlags, c.App.Writer) }, } return json } -func jsonMain(flags jsonFlags) error { +func jsonMain(flags jsonFlags, out io.Writer) error { fmt.Println(flags) @@ -53,7 +54,7 @@ func jsonMain(flags jsonFlags) error { } jsonBytes, _ := options.Marshal(scipIndex) - fmt.Println(string(jsonBytes)) + out.Write(jsonBytes) return nil } diff --git a/cmd/json_test.go b/cmd/json_test.go new file mode 100644 index 00000000..78631558 --- /dev/null +++ b/cmd/json_test.go @@ -0,0 +1,69 @@ +package main + +import ( + "bytes" + "encoding/json" + "io" + "io/ioutil" + "log" + "os" + "testing" + + "github.com/sourcegraph/scip/bindings/go/scip" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" +) + +func TestJSONCommand(t *testing.T) { + app := scipApp() + // Redirect CLI writer to a buffer + var buff bytes.Buffer + app.Writer = io.Writer(&buff) + idx := makeIndex([]string{"a"}, stringMap{"f": {"b"}}, stringMap{"f": {"a", "b"}}) + + idx.Metadata = &scip.Metadata{ProjectRoot: "howdy"} + + // Serialise SCIP index + indexBytes, err := proto.Marshal(idx) + + // Write SCIP index to a temp file + dir := os.TempDir() + file, err := ioutil.TempFile(dir, "scip-cli-json-test*.scip") + if err != nil { + log.Fatal(err) + } + defer os.Remove(file.Name()) + + _, fErr := file.Write(indexBytes) + if fErr != nil { + log.Fatal(fErr) + } + + // Run the JSON command with the temporary file + runErr := app.Run([]string{"scip", "json", "--from", file.Name()}) + if runErr != nil { + log.Fatal(runErr) + } + + type JsonIndex struct { + Metadata struct { + ProjectRoot string `json:"projectRoot"` + } + Documents []struct { + RelativePath string `json:"relativePath"` + } `json:"documents"` + } + + var roundtripResult JsonIndex + + bytes := buff.Bytes() + + jsonErr := json.Unmarshal(bytes, &roundtripResult) + if jsonErr != nil { + log.Fatal(jsonErr) + } + + require.Equal(t, roundtripResult.Metadata.ProjectRoot, "howdy") + require.Equal(t, len(roundtripResult.Documents), 1) + require.Equal(t, roundtripResult.Documents[0].RelativePath, "f") +} From d7fd6f49c70935e5423d08b287e2f51d7d3634d9 Mon Sep 17 00:00:00 2001 From: Anton Sviridov Date: Tue, 2 May 2023 14:04:21 +0100 Subject: [PATCH 6/9] Remove spurious println --- cmd/json.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmd/json.go b/cmd/json.go index 0b27f558..f3e801ed 100644 --- a/cmd/json.go +++ b/cmd/json.go @@ -41,9 +41,6 @@ func jsonCommand() cli.Command { } func jsonMain(flags jsonFlags, out io.Writer) error { - - fmt.Println(flags) - scipIndex, err := readFromOption(flags.from) if err != nil { return err From 9ece64bef9d414ee454db2a966355d9322b2772a Mon Sep 17 00:00:00 2001 From: Anton Sviridov Date: Tue, 2 May 2023 14:08:29 +0100 Subject: [PATCH 7/9] ... and the module import --- cmd/json.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/json.go b/cmd/json.go index f3e801ed..089c61d1 100644 --- a/cmd/json.go +++ b/cmd/json.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "io" "github.com/sourcegraph/sourcegraph/lib/errors" From 4f044fdd75eeee62b9ed033ed90fc375ba26533c Mon Sep 17 00:00:00 2001 From: Anton Sviridov Date: Wed, 3 May 2023 09:48:09 +0100 Subject: [PATCH 8/9] Replace json subcommand with --json flag in print command --- cmd/json.go | 56 ----------------------------- cmd/main.go | 3 +- cmd/print.go | 37 ++++++++++++++----- cmd/{json_test.go => print_test.go} | 4 +-- docs/CLI.md | 17 +-------- 5 files changed, 33 insertions(+), 84 deletions(-) delete mode 100644 cmd/json.go rename cmd/{json_test.go => print_test.go} (92%) diff --git a/cmd/json.go b/cmd/json.go deleted file mode 100644 index 089c61d1..00000000 --- a/cmd/json.go +++ /dev/null @@ -1,56 +0,0 @@ -package main - -import ( - "io" - - "github.com/sourcegraph/sourcegraph/lib/errors" - "github.com/urfave/cli/v2" - "google.golang.org/protobuf/encoding/protojson" -) - -type jsonFlags struct { - from string - pretty bool -} - -func jsonCommand() cli.Command { - var jsonFlags jsonFlags - - json := cli.Command{ - Name: "json", - Usage: "Print SCIP index as JSON", - Flags: []cli.Flag{ - fromFlag(&jsonFlags.from), - &cli.BoolFlag{ - Name: "pretty", - Usage: "Pretty print (multiline, with indentation)", - Aliases: []string{"p"}, - Destination: &jsonFlags.pretty, - }, - }, - Action: func(c *cli.Context) error { - if jsonFlags.from == "" { - return errors.New("missing argument for path to SCIP index") - } - return jsonMain(jsonFlags, c.App.Writer) - }, - } - - return json -} - -func jsonMain(flags jsonFlags, out io.Writer) error { - scipIndex, err := readFromOption(flags.from) - if err != nil { - return err - } - - options := protojson.MarshalOptions{ - Multiline: flags.pretty, - } - - jsonBytes, _ := options.Marshal(scipIndex) - out.Write(jsonBytes) - - return nil -} diff --git a/cmd/main.go b/cmd/main.go index c0f80080..986e8fdc 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -24,8 +24,7 @@ func commands() []*cli.Command { print := printCommand() snapshot := snapshotCommand() stats := statsCommand() - json := jsonCommand() - return []*cli.Command{&convert, &lint, &print, &snapshot, &stats, &json} + return []*cli.Command{&convert, &lint, &print, &snapshot, &stats} } //go:embed version.txt diff --git a/cmd/print.go b/cmd/print.go index a5101a8d..6ba57206 100644 --- a/cmd/print.go +++ b/cmd/print.go @@ -1,38 +1,59 @@ package main import ( + "io" + "math" + "github.com/k0kubun/pp/v3" "github.com/urfave/cli/v2" - "math" + "google.golang.org/protobuf/encoding/protojson" "github.com/sourcegraph/sourcegraph/lib/errors" ) func printCommand() cli.Command { + var json bool snapshot := cli.Command{ Name: "print", Usage: "Print a SCIP index in a human-readable format for debugging", Description: `WARNING: The output may change over time. Do not rely on the output of this command in scripts`, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "json", + Usage: "Output in JSON format", + Destination: &json, + }, + }, Action: func(c *cli.Context) error { indexPath := c.Args().Get(0) if indexPath == "" { return errors.New("missing argument for path to SCIP index") } - return printMain(indexPath) + return printMain(indexPath, json, c.App.Writer) }, } return snapshot } -func printMain(indexPath string) error { +func printMain(indexPath string, json bool, out io.Writer) error { index, err := readFromOption(indexPath) if err != nil { return err } - pp.BufferFoldThreshold = math.MaxInt - prettyPrinter := pp.New() - prettyPrinter.SetExportedOnly(true) - _, err = prettyPrinter.Print(index) - return err + if json { + pp.BufferFoldThreshold = math.MaxInt + + options := protojson.MarshalOptions{} + + jsonBytes, err := options.Marshal(index) + out.Write(jsonBytes) + return err + } else { + prettyPrinter := pp.New() + prettyPrinter.SetExportedOnly(true) + prettyPrinter.SetOutput(out) + _, err = prettyPrinter.Print(index) + return err + } } diff --git a/cmd/json_test.go b/cmd/print_test.go similarity index 92% rename from cmd/json_test.go rename to cmd/print_test.go index 78631558..a5f78b28 100644 --- a/cmd/json_test.go +++ b/cmd/print_test.go @@ -14,7 +14,7 @@ import ( "google.golang.org/protobuf/proto" ) -func TestJSONCommand(t *testing.T) { +func TestJSONPrinting(t *testing.T) { app := scipApp() // Redirect CLI writer to a buffer var buff bytes.Buffer @@ -40,7 +40,7 @@ func TestJSONCommand(t *testing.T) { } // Run the JSON command with the temporary file - runErr := app.Run([]string{"scip", "json", "--from", file.Name()}) + runErr := app.Run([]string{"scip", "print", "--json", file.Name()}) if runErr != nil { log.Fatal(runErr) } diff --git a/docs/CLI.md b/docs/CLI.md index 4683db46..6b71e190 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -8,7 +8,6 @@ - [`scip print`](#scip-print) - [`scip snapshot`](#scip-snapshot) - [`scip stats`](#scip-stats) - - [`scip json`](#scip-json) ``` @@ -90,6 +89,7 @@ DESCRIPTION: OPTIONS: --help, -h show help (default: false) + --json Output in JSON format (default: false) ``` ## `scip snapshot` @@ -128,18 +128,3 @@ USAGE: OPTIONS: --from value Path to SCIP index file (default: index.scip) ``` - -## `scip json` - -``` -NAME: - scip json - Print SCIP index as JSON - -USAGE: - scip json [command options] [arguments...] - -OPTIONS: - --from value Path to SCIP index file (default: "index.scip") - --help, -h show help (default: false) - --pretty, -p Pretty print (multiline, with indentation) (default: false) -``` From e705756d304ed8462ed7351832acebe37ce1a1ff Mon Sep 17 00:00:00 2001 From: Anton Sviridov Date: Wed, 3 May 2023 09:50:17 +0100 Subject: [PATCH 9/9] Update CLI.md --- docs/CLI.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/CLI.md b/docs/CLI.md index 6b71e190..61d27209 100644 --- a/docs/CLI.md +++ b/docs/CLI.md @@ -31,12 +31,12 @@ COMMANDS: print Print a SCIP index in a human-readable format for debugging snapshot Generate snapshot files for golden testing stats Output useful statistics about a SCIP index - json Print SCIP index as JSON help, h Shows a list of commands or help for one command GLOBAL OPTIONS: --help, -h show help (default: false) --version, -v print the version (default: false) + ``` ## `scip convert`