Class: Rigor::LanguageServer::DiagnosticPublisher

Inherits:
Object
  • Object
show all
Defined in:
lib/rigor/language_server/diagnostic_publisher.rb

Overview

Converts buffer state into ‘textDocument/publishDiagnostics` notifications. Owns the Rigor `Analysis::Runner` orchestration for the per-buffer single-file scope path that editor mode v1 already supports — every `publish_for(uri)` call materialises a `BufferBinding` from the BufferTable entry, runs the Runner, and pushes the resulting LSP `Diagnostic[]` through the writer.

Slice 4 is synchronous: each call blocks until analysis completes (typically 100-300ms warm). Debouncing (200ms quiet-time before publish) and Ractor-pool dispatch are queued for slice 4b / slice 8 respectively.

Constant Summary collapse

SEVERITY_MAP =

Maps Rigor severity symbols to LSP DiagnosticSeverity integers per spec § “Diagnostic”:

1 = Error, 2 = Warning, 3 = Information, 4 = Hint.
{
  error: 1,
  warning: 2,
  info: 3,
  hint: 4
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(writer:, buffer_table:, project_context:, debouncer: nil, debounce_seconds: 0.2) ⇒ DiagnosticPublisher

Returns a new instance of DiagnosticPublisher.

Parameters:

  • debouncer (Rigor::LanguageServer::Debouncer, nil) (defaults to: nil)

    when present, ‘publish_for` schedules its work through the debouncer (cancels prior pending task for the same URI, fires after `debounce_seconds` quiet-time). Nil keeps the slice 4-7 synchronous behaviour — primarily useful for specs.

  • debounce_seconds (Numeric) (defaults to: 0.2)

    quiet-time before the debounced publish fires. 0 with a debouncer means “schedule on next-tick” (still async); without a debouncer the value is unused.



43
44
45
46
47
48
49
50
# File 'lib/rigor/language_server/diagnostic_publisher.rb', line 43

def initialize(writer:, buffer_table:, project_context:,
               debouncer: nil, debounce_seconds: 0.2)
  @writer = writer
  @buffer_table = buffer_table
  @project_context = project_context
  @debouncer = debouncer
  @debounce_seconds = debounce_seconds
end

Instance Method Details

#cancel_pendingObject

Cancels every in-flight debounced task. Called from ‘Server#handle_shutdown` so pending publishes don’t fire against a closed STDOUT.



80
81
82
# File 'lib/rigor/language_server/diagnostic_publisher.rb', line 80

def cancel_pending
  @debouncer&.cancel_all
end

#publish_empty(uri) ⇒ Object

Publishes an EMPTY diagnostic array for ‘uri`. The LSP-spec idiom for “clear inline markers” — called from `didClose` so clients drop stale highlights when the user closes a buffer.



73
74
75
# File 'lib/rigor/language_server/diagnostic_publisher.rb', line 73

def publish_empty(uri)
  notify(uri, [])
end

#publish_for(uri) ⇒ Object

Run analysis for the buffer at ‘uri` (looked up in the BufferTable) and push a `textDocument/publishDiagnostics` notification. No-op when the URI isn’t a ‘file://` form or the buffer isn’t currently open. When a Debouncer is wired, the analysis is scheduled async per the configured ‘debounce_seconds`; otherwise it runs inline.



58
59
60
61
62
63
64
65
66
67
# File 'lib/rigor/language_server/diagnostic_publisher.rb', line 58

def publish_for(uri)
  path = Uri.to_path(uri)
  return if path.nil?

  if @debouncer
    @debouncer.schedule(uri, delay: @debounce_seconds) { run_and_notify(uri, path) }
  else
    run_and_notify(uri, path)
  end
end