| // Copyright 2018 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // The golsp command is an LSP server for Go. |
| // The Language Server Protocol allows any text editor |
| // to be extended with IDE-like features; |
| // see https://langserver.org/ for details. |
| package main // import "golang.org/x/tools/cmd/golsp" |
| |
| import ( |
| "context" |
| "flag" |
| "fmt" |
| "io" |
| "log" |
| "os" |
| "runtime" |
| "runtime/pprof" |
| "runtime/trace" |
| |
| "golang.org/x/tools/internal/jsonrpc2" |
| "golang.org/x/tools/internal/lsp" |
| ) |
| |
| var ( |
| cpuprofile = flag.String("cpuprofile", "", "write CPU profile to this file") |
| memprofile = flag.String("memprofile", "", "write memory profile to this file") |
| traceFlag = flag.String("trace", "", "write trace log to this file") |
| |
| // Flags for compatitibility with VSCode. |
| logfile = flag.String("logfile", "", "filename to log to") |
| mode = flag.String("mode", "", "no effect") |
| ) |
| |
| func main() { |
| flag.Usage = func() { |
| fmt.Fprintf(os.Stderr, "usage: golsp [flags]\n") |
| flag.PrintDefaults() |
| } |
| flag.Parse() |
| if flag.NArg() > 0 { |
| flag.Usage() |
| os.Exit(2) |
| } |
| |
| if *cpuprofile != "" { |
| f, err := os.Create(*cpuprofile) |
| if err != nil { |
| log.Fatal(err) |
| } |
| if err := pprof.StartCPUProfile(f); err != nil { |
| log.Fatal(err) |
| } |
| // NB: profile won't be written in case of error. |
| defer pprof.StopCPUProfile() |
| } |
| |
| if *traceFlag != "" { |
| f, err := os.Create(*traceFlag) |
| if err != nil { |
| log.Fatal(err) |
| } |
| if err := trace.Start(f); err != nil { |
| log.Fatal(err) |
| } |
| // NB: trace log won't be written in case of error. |
| defer func() { |
| trace.Stop() |
| log.Printf("To view the trace, run:\n$ go tool trace view %s", *traceFlag) |
| }() |
| } |
| |
| if *memprofile != "" { |
| f, err := os.Create(*memprofile) |
| if err != nil { |
| log.Fatal(err) |
| } |
| // NB: memprofile won't be written in case of error. |
| defer func() { |
| runtime.GC() // get up-to-date statistics |
| if err := pprof.WriteHeapProfile(f); err != nil { |
| log.Fatalf("Writing memory profile: %v", err) |
| } |
| f.Close() |
| }() |
| } |
| |
| if *logfile != "" { |
| f, err := os.Create(*logfile) |
| if err != nil { |
| log.Fatalf("Unable to create log file: %v", err) |
| } |
| defer f.Close() |
| log.SetOutput(io.MultiWriter(os.Stderr, f)) |
| } |
| if err := run(context.Background()); err != nil { |
| log.Fatal(err) |
| } |
| } |
| |
| func run(ctx context.Context) error { |
| return lsp.RunServer(ctx, jsonrpc2.NewHeaderStream(os.Stdin, os.Stdout), jsonrpc2.Log) |
| } |