lib/steep/server/code_worker.rb in steep-0.39.0 vs lib/steep/server/code_worker.rb in steep-0.40.0

- old
+ new

@@ -1,10 +1,13 @@ module Steep module Server class CodeWorker < BaseWorker LSP = LanguageServer::Protocol + TypeCheckJob = Struct.new(:target, :path, keyword_init: true) + StatsJob = Struct.new(:request, :paths, keyword_init: true) + include Utils attr_reader :typecheck_paths attr_reader :queue @@ -15,11 +18,11 @@ @queue = queue end def enqueue_type_check(target:, path:) Steep.logger.info "Enqueueing type check: #{target.name}::#{path}..." - queue << [target, path] + queue << TypeCheckJob.new(target: target, path: path) end def typecheck_file(path, target) Steep.logger.info "Starting type checking: #{target.name}::#{path}..." @@ -41,10 +44,27 @@ diagnostics: diagnostics ) ) end + def calculate_stats(request_id, paths) + calculator = Project::StatsCalculator.new(project: project) + + stats = paths.map do |path| + if typecheck_paths.include?(path) + if target = project.target_for_source_path(path) + calculator.calc_stats(target, path) + end + end + end.compact + + writer.write( + id: request_id, + result: stats.map(&:as_json) + ) + end + def source_diagnostics(source, options) case status = source.status when Project::SourceFile::ParseErrorStatus [] when Project::SourceFile::AnnotationSyntaxErrorStatus @@ -63,49 +83,39 @@ ) ) ) ] when Project::SourceFile::TypeCheckStatus - status.typing.errors.select {|error| options.error_to_report?(error) }.map do |error| - loc = error.location_to_str - - LSP::Interface::Diagnostic.new( - message: StringIO.new.tap {|io| error.print_to(io) }.string.gsub(/\A#{Regexp.escape(loc)}: /, "").chomp, - severity: LSP::Constant::DiagnosticSeverity::ERROR, - range: LSP::Interface::Range.new( - start: LSP::Interface::Position.new( - line: error.node.loc.line - 1, - character: error.node.loc.column - ), - end: LSP::Interface::Position.new( - line: error.node.loc.last_line - 1, - character: error.node.loc.last_column - ) - ) - ) - end + formatter = Diagnostic::LSPFormatter.new() + status.typing.errors.select {|error| options.error_to_report?(error) }.map {|error| formatter.format(error) } when Project::SourceFile::TypeCheckErrorStatus [] end end def handle_request(request) case request[:method] when "initialize" - # Don't respond to initialize request, but start type checking. project.targets.each do |target| target.source_files.each_key do |path| if typecheck_paths.include?(path) enqueue_type_check(target: target, path: path) end end end + writer.write({ id: request[:id], result: nil }) + when "workspace/executeCommand" - if request[:params][:command] == "steep/registerSourceToWorker" + Steep.logger.info { "Executing command: #{request[:params][:command]}, arguments=#{request[:params][:arguments].map(&:inspect).join(", ")}" } + case request[:params][:command] + when "steep/registerSourceToWorker" paths = request[:params][:arguments].map {|arg| source_path(URI.parse(arg)) } typecheck_paths.merge(paths) + when "steep/stats" + paths = request[:params][:arguments].map {|arg| source_path(URI.parse(arg)) } + queue << StatsJob.new(paths: paths, request: request) end when "textDocument/didChange" update_source(request) do |path, _| source_target, signature_targets = project.targets_for_path(path) @@ -126,12 +136,15 @@ end end end def handle_job(job) - target, path = job - - typecheck_file(path, target) + case job + when TypeCheckJob + typecheck_file(job.path, job.target) + when StatsJob + calculate_stats(job.request[:id], job.paths) + end end end end end