func NewStreamServer(cache *cache.Cache, daemon bool, optionsFunc func(*settings.Options)) jsonrpc2.StreamServer {return &streamServer{cache: cache, daemon: daemon, optionsOverrides: optionsFunc}}
type streamServer struct {cache *cache.Cache// daemon controls whether or not to log new connections.daemon bool// optionsOverrides is passed to newly created sessions.optionsOverrides func(*settings.Options)// serverForTest may be set to a test fake for testing.serverForTest protocol.Server}
func (s *streamServer) ServeStream(ctx context.Context, conn jsonrpc2.Conn) error {client := protocol.ClientDispatcher(conn)session := cache.NewSession(ctx, s.cache)svr := s.serverForTestif svr == nil {options := settings.DefaultOptions(s.optionsOverrides)svr = server.New(session, client, options)if instance := debug.GetInstance(ctx); instance != nil {instance.AddService(svr, session)}}// Clients may or may not send a shutdown message. Make sure the server is// shut down.// TODO(rFindley): this shutdown should perhaps be on a disconnected context.defer func() {if err := svr.Shutdown(ctx); err != nil {event.Error(ctx, "error shutting down", err)}}()executable, err := os.Executable()if err != nil {log.Printf("error getting gopls path: %v", err)executable = ""}ctx = protocol.WithClient(ctx, client)conn.Go(ctx,protocol.Handlers(handshaker(session, executable, s.daemon,protocol.ServerHandler(svr,jsonrpc2.MethodNotFound))))if s.daemon {log.Printf("Session %s: connected", session.ID())defer log.Printf("Session %s: exited", session.ID())}<-conn.Done()return conn.Err()}
func ClientDispatcher(conn jsonrpc2.Conn) ClientCloser {return &clientDispatcher{sender: clientConn{conn}}}
type clientDispatcher struct {sender connSender}
conn.Go(ctx,protocol.Handlers(handshaker(session, executable, s.daemon,protocol.ServerHandler(svr,jsonrpc2.MethodNotFound))))
func handshaker(session *cache.Session, goplsPath string, logHandshakes bool, handler jsonrpc2.Handler) jsonrpc2.Handler {return func(ctx context.Context, reply jsonrpc2.Replier, r jsonrpc2.Request) error {switch r.Method() {case handshakeMethod:// We log.Printf in this handler, rather than event.Log when we want logs// to go to the daemon log rather than being reflected back to the// client.var req handshakeRequestif err := json.Unmarshal(r.Params(), &req); err != nil {if logHandshakes {log.Printf("Error processing handshake for session %s: %v", session.ID(), err)}sendError(ctx, reply, err)return nil}if logHandshakes {log.Printf("Session %s: got handshake. Logfile: %q, Debug addr: %q", session.ID(), req.Logfile, req.DebugAddr)}event.Log(ctx, "Handshake session update",cache.KeyUpdateSession.Of(session),label.DebugAddress.Of(req.DebugAddr),label.Logfile.Of(req.Logfile),label.ServerID.Of(req.ServerID),label.GoplsPath.Of(req.GoplsPath),)resp := handshakeResponse{SessionID: session.ID(),GoplsPath: goplsPath,}if di := debug.GetInstance(ctx); di != nil {resp.Logfile = di.Logfileresp.DebugAddr = di.ListenedDebugAddress()}return reply(ctx, resp, nil)case sessionsMethod:resp := serverState{GoplsPath: goplsPath,CurrentClientID: session.ID(),}if di := debug.GetInstance(ctx); di != nil {resp.Logfile = di.Logfileresp.DebugAddr = di.ListenedDebugAddress()for _, c := range di.State.Clients() {resp.Clients = append(resp.Clients, clientSession{SessionID: c.Session.ID(),Logfile: c.Logfile,DebugAddr: c.DebugAddress,})}}return reply(ctx, resp, nil)}return handler(ctx, reply, r)}}
const (handshakeMethod = "gopls/handshake"sessionsMethod = "gopls/sessions")
func New(session *cache.Session, client protocol.ClientCloser, options *settings.Options) protocol.Server {const concurrentAnalyses = 1// If this assignment fails to compile after a protocol// upgrade, it means that one or more new methods need new// stub declarations in unimplemented.go.return &server{diagnostics: make(map[protocol.DocumentURI]*fileDiagnostics),watchedGlobPatterns: nil, // emptychangedFiles: make(map[protocol.DocumentURI]unit),session: session,client: client,diagnosticsSema: make(chan unit, concurrentAnalyses),progress: progress.NewTracker(client),options: options,viewsToDiagnose: make(map[*cache.View]uint64),}}


文章转载自golang算法架构leetcode技术php,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




