Class: Pikuri::Lsp::Operation
- Inherits:
-
Object
- Object
- Pikuri::Lsp::Operation
- Defined in:
- lib/pikuri/lsp/operation.rb
Overview
One value of the lsp tool's operation enum: what the model may ask for,
which LSP request answers it, which capability the server must advertise
first, and how the answer is rendered.
Operation['goToDefinition'].capability # => "definitionProvider"
Operation['incomingCalls'].prepare # => "textDocument/prepareCallHierarchy"
Operation.names.size # => 10
Eight names are the surface three shipped harnesses converged on, kept
verbatim so they match what a model has seen elsewhere; goToTypeDefinition
and supertypes are measured additions.
Static enum, gate at dispatch
Capabilities are per workspace, not per binary (ClientWrapper#supports?), and two registered servers have different sets — so a schema computed from them would have to advertise the union anyway, and would move whenever a server restarted or a project gained a formatter. A moving tool description is worse than a static one the model can learn.
Three absences that are decisions
Each looks like an obvious addition, so each is worth a line:
prepareCallHierarchy is out because exposing it hands the model an opaque
CallHierarchyItem to hold and echo back — the tool runs the prepare hop
itself; subtypes is out because goToImplementation answers the same
question transitively in one call on the one server whose subtypes is not
a # TODO stub; and the write-side operations (rename, formatting, code
actions) are what this gem refuses to become.
Constant Summary collapse
- ALL =
Every operation, in the order the tool description lists them.
[ new(name: 'goToDefinition', capability: 'definitionProvider', request: 'textDocument/definition', anchor: :position, shape: :locations, cap: 20, summary: 'where a name is defined. Several answers are normal — a reopened Ruby ' \ 'namespace and a dynamically dispatched method both have more than one.'), new(name: 'findReferences', capability: 'referencesProvider', request: 'textDocument/references', anchor: :position, shape: :locations, cap: 40, summary: 'every use of a name, declarations included — textual uses of the ' \ 'name, not only calls of it.'), new(name: 'hover', capability: 'hoverProvider', request: 'textDocument/hover', anchor: :position, shape: :hover, cap: 1, summary: 'the documentation and signature a server holds for a name — often the ' \ 'whole class comment, and the one operation that answers for a library ' \ 'symbol whose source is not on disk.'), new(name: 'documentSymbol', capability: 'documentSymbolProvider', request: 'textDocument/documentSymbol', anchor: :document, shape: :symbols, cap: 200, summary: 'the outline of one file, filtered to `symbol` when it matches a row — ' \ 'the way to find a method the project-wide index does not hold.'), new(name: 'workspaceSymbol', capability: 'workspaceSymbolProvider', request: 'workspace/symbol', anchor: :query, shape: :symbols, cap: 25, summary: 'search the server\'s whole index by name, which reaches inside ' \ 'dependencies; matching is fuzzy.'), new(name: 'goToImplementation', capability: 'implementationProvider', request: 'textDocument/implementation', anchor: :position, shape: :locations, cap: 25, summary: 'what implements or overrides this — an interface to its implementors, a ' \ 'method to its overriders, and on some servers a class to every subclass ' \ 'below it.'), new(name: 'goToTypeDefinition', capability: 'typeDefinitionProvider', request: 'textDocument/typeDefinition', anchor: :position, shape: :locations, cap: 10, summary: 'the *type* of an expression rather than its declaration — the only way ' \ 'to recover a type written nowhere in the source, as with an inferred local.'), new(name: 'incomingCalls', capability: 'callHierarchyProvider', prepare: 'textDocument/prepareCallHierarchy', request: 'callHierarchy/incomingCalls', anchor: :position, shape: :calls, cap: 40, summary: 'which functions call this one, resolved through the call graph rather ' \ 'than by name — narrower and more exact than findReferences.'), new(name: 'outgoingCalls', capability: 'callHierarchyProvider', prepare: 'textDocument/prepareCallHierarchy', request: 'callHierarchy/outgoingCalls', anchor: :position, shape: :calls, cap: 40, summary: 'what this calls, without reading the body.'), new(name: 'supertypes', capability: 'typeHierarchyProvider', prepare: 'textDocument/prepareTypeHierarchy', request: 'typeHierarchy/supertypes', anchor: :position, shape: :supertypes, cap: 8, summary: 'the ancestor chain of a class, walked level by level to the root — not ' \ 'the one level a definition hop on the superclass name would give.') ].freeze
- BY_NAME =
Returns ALL keyed by #name.
ALL.to_h { |operation| [operation.name, operation] }.freeze
Class Method Summary collapse
-
.[](name) ⇒ Operation?
nilfor a name outside the enum, whichTool::Parametersrefuses before this is reached. -
.names ⇒ Array<String>
Every enum value, in ALL's order — what the tool's
operationparameter advertises.
Instance Method Summary collapse
-
#grouped? ⇒ Boolean
Whether results get the source/tests split.
-
#initialize(name:, capability:, request:, anchor:, shape:, cap:, summary:, prepare: nil) ⇒ Operation
constructor
A new instance of Operation.
Constructor Details
#initialize(name:, capability:, request:, anchor:, shape:, cap:, summary:, prepare: nil) ⇒ Operation
Returns a new instance of Operation.
36 37 38 |
# File 'lib/pikuri/lsp/operation.rb', line 36 def initialize(name:, capability:, request:, anchor:, shape:, cap:, summary:, prepare: nil) super end |
Class Method Details
Instance Method Details
#grouped? ⇒ Boolean
Returns whether results get the source/tests split. True for the two operations whose volume is dominated by test files — 40 references to one method were 4 call sites, 2 declarations and 34 spec hits, and the 4 are what the model asked for.
44 45 46 |
# File 'lib/pikuri/lsp/operation.rb', line 44 def grouped? %w[findReferences incomingCalls].include?(name) end |