// 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) }