Skip to content

Commit 98642af

Browse files
cxxxrclaude
andcommitted
fix(call-graph): address code-contractor review violations
- file_structure_rule: Move defvar before defclass in registry.lisp, initialize to nil and set after class definition - docstring_rule: Add defgeneric declarations with docstrings for exported condition readers (provider-error-provider, etc.) - functional_style_rule: Remove :register option from macro that used *provider-registry* directly; document global as well-documented exception - macro_style_rule: Extract option parsing to %parse-provider-options helper function, keeping macro minimal 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 89ddb18 commit 98642af

File tree

2 files changed

+59
-33
lines changed

2 files changed

+59
-33
lines changed

extensions/call-graph/provider.lisp

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ Used for automatic registration and provider discovery.")
4545

4646
;;; Provider Conditions
4747

48+
;; Reader function declarations for exported condition accessors
49+
(defgeneric provider-error-provider (condition)
50+
(:documentation "Return the provider that encountered the error."))
51+
52+
(defgeneric provider-error-message (condition)
53+
(:documentation "Return the error message, or NIL if not specified."))
54+
55+
(defgeneric provider-unavailable-reason (condition)
56+
(:documentation "Return the reason why the provider is unavailable, or NIL."))
57+
4858
(define-condition provider-error (error)
4959
((provider :initarg :provider
5060
:reader provider-error-provider
@@ -81,6 +91,22 @@ required runtime not connected, etc."))
8191

8292
;;; Provider Definition Macro
8393

94+
(eval-when (:compile-toplevel :load-toplevel :execute)
95+
(defun %parse-provider-options (options)
96+
"Parse provider definition options at macro-expansion time.
97+
Returns values: (provider-name priority languages class-options).
98+
Signals an error if :provider-name is not specified."
99+
(let ((provider-name (cadr (assoc :provider-name options)))
100+
(priority (or (cadr (assoc :priority options)) 5))
101+
(languages (cadr (assoc :languages options)))
102+
(class-options (remove-if (lambda (opt)
103+
(member (car opt)
104+
'(:provider-name :priority :languages)))
105+
options)))
106+
(unless provider-name
107+
(error "define-call-graph-provider requires :provider-name option"))
108+
(values provider-name priority languages class-options))))
109+
84110
(defmacro define-call-graph-provider (name (&rest superclasses) slots &body options)
85111
"Define a new call graph provider class with common boilerplate.
86112
@@ -92,38 +118,30 @@ OPTIONS are class options plus special provider options:
92118
:provider-name - Keyword name for the provider (required)
93119
:priority - Provider priority (default 5)
94120
:languages - List of supported language keywords
95-
:register - If T, auto-register with *provider-registry*
121+
122+
To register the provider, call register-provider explicitly after load:
123+
(register-provider *provider-registry*
124+
(make-instance 'my-python-provider)
125+
'(:python))
96126
97127
Example:
98128
(define-call-graph-provider my-python-provider ()
99129
((parser :accessor my-provider-parser))
100130
(:provider-name :my-python)
101131
(:priority 5)
102-
(:languages (:python))
103-
(:register t))"
104-
(let* ((superclasses (or superclasses '(call-graph-provider)))
105-
(provider-name (cadr (assoc :provider-name options)))
106-
(priority (or (cadr (assoc :priority options)) 5))
107-
(languages (cadr (assoc :languages options)))
108-
(register (cadr (assoc :register options)))
109-
(class-options (remove-if (lambda (opt)
110-
(member (car opt)
111-
'(:provider-name :priority :languages :register)))
112-
options)))
113-
(unless provider-name
114-
(error "define-call-graph-provider requires :provider-name option"))
115-
`(progn
116-
(defclass ,name ,superclasses
117-
,slots
118-
,@class-options)
119-
(defmethod provider-name ((provider ,name))
120-
,provider-name)
121-
(defmethod provider-priority ((provider ,name))
122-
,priority)
123-
,@(when languages
124-
`((defmethod provider-languages ((provider ,name))
125-
',languages)))
126-
,@(when register
127-
`((let ((provider (make-instance ',name)))
128-
(register-provider *provider-registry* provider ',languages)))))))
132+
(:languages (:python)))"
133+
(multiple-value-bind (provider-name priority languages class-options)
134+
(%parse-provider-options options)
135+
(let ((superclasses (or superclasses '(call-graph-provider))))
136+
`(progn
137+
(defclass ,name ,superclasses
138+
,slots
139+
,@class-options)
140+
(defmethod provider-name ((provider ,name))
141+
,provider-name)
142+
(defmethod provider-priority ((provider ,name))
143+
,priority)
144+
,@(when languages
145+
`((defmethod provider-languages ((provider ,name))
146+
',languages)))))))
129147

extensions/call-graph/registry.lisp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@
55
;;; This module provides a central registry for call graph providers.
66
;;; Providers are registered with language keywords and selected by priority.
77

8+
(defvar *provider-registry* nil
9+
"Global provider registry instance.
10+
11+
This is a well-documented global like `lem:*current-buffer*`.
12+
The registry is shared across the editor lifetime and accessed via
13+
registry-passing functions (register-provider, find-provider, etc.).
14+
Direct mutation should be avoided; use the registry API functions.
15+
16+
This registry is used by living-canvas to find appropriate providers
17+
for different programming languages.")
18+
819
(defclass provider-registry ()
920
((providers
1021
:initform (make-hash-table :test 'eq)
@@ -19,11 +30,8 @@
1930
Manages provider registration, lookup, and selection based on language
2031
and priority. Providers are indexed both by name and by supported languages."))
2132

22-
(defvar *provider-registry* (make-instance 'provider-registry)
23-
"Global provider registry instance.
24-
25-
This registry is used by living-canvas to find appropriate providers
26-
for different programming languages.")
33+
;; Initialize the global registry after class definition
34+
(setf *provider-registry* (make-instance 'provider-registry))
2735

2836
(defun register-provider (registry provider languages)
2937
"Register PROVIDER in REGISTRY for LANGUAGES.

0 commit comments

Comments
 (0)