123456789_123456789_123456789_123456789_123456789_

Class: TypeProf::LSP::Server

Relationships & Source Files
Inherits: Object
Defined in: lib/typeprof/lsp/server.rb

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(core, reader, writer, url_schema: nil, publish_all_diagnostics: false) ⇒ Server

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 47

def initialize(core, reader, writer, url_schema: nil, publish_all_diagnostics: false)
  @core = core
  @workspaces = {}
  @reader = reader
  @writer = writer
  @request_id = 0
  @running_requests_from_client = {}
  @running_requests_from_server = {}
  @open_texts = {}
  @exit = false
  @signature_enabled = true
  @url_schema = url_schema || (File::ALT_SEPARATOR != "\\" ? "file://" : "file:///")
  @publish_all_diagnostics = publish_all_diagnostics # TODO: implement more dedicated publish feature
end

Class Method Details

.start_socket(core)

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 21

def self.start_socket(core)
  Socket.tcp_server_sockets("localhost", nil) do |servs|
    serv = servs[0].local_address
    $stdout << JSON.generate({
      host: serv.ip_address,
      port: serv.ip_port,
      pid: $$,
    })
    $stdout.flush

    $stdout = $stderr

    Socket.accept_loop(servs) do |sock|
      sock.set_encoding("UTF-8")
      begin
        reader = Reader.new(sock)
        writer = Writer.new(sock)
        new(core, reader, writer).run
      ensure
        sock.close
      end
      exit
    end
  end
end

.start_stdio(core)

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 11

def self.start_stdio(core)
  $stdin.binmode
  $stdout.binmode
  reader = Reader.new($stdin)
  writer = Writer.new($stdout)
  # pipe all builtin print output to stderr to avoid conflicting with lsp
  $stdout = $stderr
  new(core, reader, writer).run
end

Instance Attribute Details

#core (readonly)

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 62

attr_reader :core, :open_texts

#open_texts (readonly)

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 62

attr_reader :core, :open_texts

#signature_enabled (rw)

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 63

attr_accessor :signature_enabled

Instance Method Details

#add_workspaces(folders)

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 73

def add_workspaces(folders)
  folders.each do |path|
    conf_path = File.join(path, "typeprof.conf.json")
    if File.readable?(conf_path)
      conf = TypeProf::LSP.load_json_with_comments(conf_path, symbolize_names: true)
      if conf
        if conf[:typeprof_version] == "experimental"
          if conf[:analysis_unit_dirs].size >= 2
             puts "currently analysis_unit_dirs can have only one directory"
          end
          conf[:analysis_unit_dirs].each do |dir|
            dir = File.expand_path(dir, path)
            @workspaces[dir] = true
            @core.add_workspace(dir, conf[:rbs_dir])
          end
        else
          puts "Unknown typeprof_version: #{ conf[:typeprof_version] }"
        end
      end
    else
      puts "typeprof.conf.json is not found"
    end
  end
end

#cancel_request(id)

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 141

def cancel_request(id)
  req = @running_requests_from_client[id]
  req.cancel if req.respond_to?(:cancel)
end

#exit

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 146

def exit
  @exit = true
end

#path_to_uri(path)

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 65

def path_to_uri(path)
  @url_schema + File.expand_path(path)
end

#publish_diagnostics(uri)

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 150

def publish_diagnostics(uri)
  (@publish_all_diagnostics ? @open_texts : [[uri, @open_texts[uri]]]).each do |uri, text|
    diags = []
    if text
      @core.diagnostics(text.path) do |diag|
        diags << diag.to_lsp
      end
    end
    send_notification(
      "textDocument/publishDiagnostics",
      uri: uri,
      diagnostics: diags
    )
  end
end

#run

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 105

def run
  @reader.read do |json|
    if json[:method]
      # request or notification
      msg_class = Message.find(json[:method])
      if msg_class
        msg = msg_class.new(self, json)
        @running_requests_from_client[json[:id]] = msg if json[:id]
        msg.run
      else

      end
    else
      # response
      callback = @running_requests_from_server.delete(json[:id])
      callback&.call(json[:params], json[:error])
    end
    break if @exit
  end
end

#send_notification(method, **params)

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 131

def send_notification(method, **params)
  @writer.write(method: method, params: params)
end

#send_request(method, **params, &blk)

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 135

def send_request(method, **params, &blk)
  id = @request_id += 1
  @running_requests_from_server[id] = blk
  @writer.write(id: id, method: method, params: params)
end

#send_response(**msg)

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 126

def send_response(**msg)
  @running_requests_from_client.delete(msg[:id])
  @writer.write(**msg)
end

#target_path?(path) ⇒ Boolean

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 98

def target_path?(path)
  @workspaces.each do |folder, _|
    return true if path.start_with?(folder)
  end
  return false
end

#uri_to_path(url)

[ GitHub ]

  
# File 'lib/typeprof/lsp/server.rb', line 69

def uri_to_path(url)
  url.delete_prefix(@url_schema)
end