golang.org/x/tools/gopls@v0.15.3/api-diff/api_diff.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build go1.18 6 // +build go1.18 7 8 package main 9 10 import ( 11 "bytes" 12 "encoding/json" 13 "flag" 14 "fmt" 15 "log" 16 "os" 17 "os/exec" 18 19 "github.com/google/go-cmp/cmp" 20 "golang.org/x/tools/gopls/internal/settings" 21 ) 22 23 const usage = `api-diff <previous version> [<current version>] 24 25 Compare the API of two gopls versions. If the second argument is provided, it 26 will be used as the new version to compare against. Otherwise, compare against 27 the current API. 28 ` 29 30 func main() { 31 flag.Parse() 32 33 if flag.NArg() < 1 || flag.NArg() > 2 { 34 fmt.Fprint(os.Stderr, usage) 35 os.Exit(2) 36 } 37 38 oldVer := flag.Arg(0) 39 newVer := "" 40 if flag.NArg() == 2 { 41 newVer = flag.Arg(1) 42 } 43 44 apiDiff, err := diffAPI(oldVer, newVer) 45 if err != nil { 46 log.Fatal(err) 47 } 48 fmt.Println("\n" + apiDiff) 49 } 50 51 func diffAPI(oldVer, newVer string) (string, error) { 52 previousAPI, err := loadAPI(oldVer) 53 if err != nil { 54 return "", fmt.Errorf("loading %s: %v", oldVer, err) 55 } 56 var currentAPI *settings.APIJSON 57 if newVer == "" { 58 currentAPI = settings.GeneratedAPIJSON 59 } else { 60 var err error 61 currentAPI, err = loadAPI(newVer) 62 if err != nil { 63 return "", fmt.Errorf("loading %s: %v", newVer, err) 64 } 65 } 66 67 return cmp.Diff(previousAPI, currentAPI), nil 68 } 69 70 func loadAPI(version string) (*settings.APIJSON, error) { 71 ver := fmt.Sprintf("golang.org/x/tools/gopls@%s", version) 72 cmd := exec.Command("go", "run", ver, "api-json") 73 74 stdout := &bytes.Buffer{} 75 stderr := &bytes.Buffer{} 76 cmd.Stdout = stdout 77 cmd.Stderr = stderr 78 79 if err := cmd.Run(); err != nil { 80 return nil, fmt.Errorf("go run failed: %v; stderr:\n%s", err, stderr) 81 } 82 apiJson := &settings.APIJSON{} 83 if err := json.Unmarshal(stdout.Bytes(), apiJson); err != nil { 84 return nil, fmt.Errorf("unmarshal: %v", err) 85 } 86 return apiJson, nil 87 }