2018-09-24 16:05:51 -06:00
|
|
|
// 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"
|
2018-09-27 09:28:20 -06:00
|
|
|
"io"
|
2018-09-24 16:05:51 -06:00
|
|
|
"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")
|
2018-09-27 09:28:20 -06:00
|
|
|
|
|
|
|
// Flags for compatitibility with VSCode.
|
|
|
|
logfile = flag.String("logfile", "", "filename to log to")
|
|
|
|
mode = flag.String("mode", "", "no effect")
|
2018-09-24 16:05:51 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
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()
|
|
|
|
}()
|
|
|
|
}
|
2018-09-27 09:28:20 -06:00
|
|
|
|
|
|
|
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))
|
|
|
|
}
|
2018-09-24 16:05:51 -06:00
|
|
|
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)
|
|
|
|
}
|