kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/languageserver/bin/main.go (about)

     1  /*
     2   * Copyright 2017 The Kythe Authors. All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *   http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  // Binary kythe_languageserver provides a Language Server Protocol v3
    18  // implementation for Kythe indexes that communicates via JSONRPC2.0 over stdio
    19  package main
    20  
    21  import (
    22  	"context"
    23  	"flag"
    24  	"fmt"
    25  	"log"
    26  	"net"
    27  	"os"
    28  	"path/filepath"
    29  	"time"
    30  
    31  	"kythe.io/kythe/go/languageserver"
    32  	"kythe.io/kythe/go/services/xrefs"
    33  
    34  	"github.com/sourcegraph/jsonrpc2"
    35  )
    36  
    37  var (
    38  	pageSize = flag.Int("page_size", 0, "Set the default xrefs page size")
    39  
    40  	serverAddr = flag.String("server", "localhost:8080",
    41  		"The address of the Kythe service to use (:8080 allows access from other machines)")
    42  )
    43  
    44  func main() {
    45  	flag.Parse()
    46  	if *serverAddr == "" {
    47  		log.Fatal("You must provide a --server address")
    48  	}
    49  
    50  	// Set up the log file
    51  	const openMode = os.O_CREATE | os.O_APPEND | os.O_WRONLY
    52  	logfile := fmt.Sprintf("kythe-ls-%s.log", time.Now().Format("20160102-150405"))
    53  	file, err := os.OpenFile(filepath.Join(os.TempDir(), logfile), openMode, os.ModePerm)
    54  	if err != nil {
    55  		log.Fatalf("Unable to create log file: %v", err)
    56  	}
    57  	log.SetOutput(file)
    58  
    59  	// Check to see that xref service is reachable. We won't hold open a
    60  	// connection to the server here, as the client manages the connection.
    61  	conn, err := net.DialTimeout("tcp", *serverAddr, 5*time.Second)
    62  	if err != nil {
    63  		log.Fatalf("Dialing Kythe service: %v", err)
    64  	}
    65  	conn.Close()
    66  
    67  	client := xrefs.WebClient("http://" + *serverAddr)
    68  	server := languageserver.NewServer(client, &languageserver.Options{
    69  		PageSize: *pageSize,
    70  	})
    71  
    72  	<-jsonrpc2.NewConn(
    73  		context.Background(),
    74  		jsonrpc2.NewBufferedStream(stdio{}, jsonrpc2.VSCodeObjectCodec{}),
    75  		languageserver.ServerHandler(&server),
    76  	).DisconnectNotify()
    77  }
    78  
    79  type stdio struct{}
    80  
    81  func (stdio) Read(data []byte) (int, error)  { return os.Stdin.Read(data) }
    82  func (stdio) Write(data []byte) (int, error) { return os.Stdout.Write(data) }
    83  func (stdio) Close() error                   { return os.Stdout.Close() }