-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathaider-code-read.el
290 lines (266 loc) · 16.4 KB
/
aider-code-read.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
;;; aider-code-read.el --- Code reading enhancement for aider.el -*- lexical-binding: t; -*-
;; Author: Kang Tu <[email protected]>
;; SPDX-License-Identifier: Apache-2.0
;;; Commentary:
;; This package enhances aider.el with code reading techniques from
;; "Code Reading: The Open Source Perspective" by Diomidis Spinellis,
;; and adds analysis for specific concerns like security, performance,
;; and maintainability.
;;; Code:
(require 'aider-core)
(require 'aider-file)
;;;###autoload
(defun aider-code-read ()
"Analyze code using various reading techniques.
Provides a selection of different code reading approaches based on context,
including general analysis and specific concerns like security or performance."
(interactive)
(let* ((function-name (which-function))
(class-name (aider--get-class-at-point))
(region-active (region-active-p))
(file-name (when buffer-file-name (file-name-nondirectory buffer-file-name)))
(dir-name (when buffer-file-name (file-name-directory buffer-file-name)))
(context-description (cond
(region-active "selected region")
(function-name (format "function '%s'" function-name))
(class-name (format "class '%s'" class-name))
(file-name (format "file '%s'" file-name))
(t "current context")))
(reading-techniques
`(("Analyze Code Unit (Bottom-up)" .
,(if region-active 'aider--analyze-code-unit-region 'aider--analyze-code-unit))
("Analyze Program Structure (Top-down)" . aider--analyze-program-structure)
,@(when function-name
'(("Analyze Dependencies (Cross-reference)" . aider--analyze-dependencies)))
("Identify Patterns (Pattern Recognition)" . aider--identify-patterns)
,@(when class-name
'(("Analyze Class (OOP Analysis)" . aider--analyze-class)))
("Analyze File (File-level)" . aider--analyze-file)
("Analyze Module (Architectural)" . aider--analyze-module)
("Plot Module Architecture (ASCII art diagram)" . aider--plot-module-architecture) ; Add new plotting function
;; --- New Specific Concern Techniques ---
("Analyze for Security Issues" . aider--analyze-for-security)
("Analyze for Performance Bottlenecks" . aider--analyze-for-performance)
("Analyze Code Quality & Maintainability" . aider--analyze-for-maintainability)
;; --- End New Techniques ---
))
(technique-names (mapcar #'car reading-techniques))
(prompt (format "Select reading technique for %s: " context-description))
(selected-technique (completing-read prompt technique-names nil t))
(technique-function (cdr (assoc selected-technique reading-techniques))))
(if technique-function
;; Ensure region analysis calls the specific function
(if (eq technique-function 'aider--analyze-code-unit-region)
(funcall technique-function)
;; Other techniques likely need file context
(progn
;; Add file context unless it's a region-specific analysis
(unless (or region-active
;; Add other functions here that *don't* need the file added automatically
(eq technique-function 'aider--analyze-module) ;; Module analysis adds files itself
(eq technique-function 'aider--plot-module-architecture) ;; Plotting adds files itself
)
(aider-add-current-file))
(funcall technique-function)))
(message "No valid reading technique selected."))))
;; --- Existing Analysis Functions (Minor change: ensure file context is added by caller) ---
(defun aider--analyze-code-unit ()
"Analyze current function using bottom-up reading technique.
Assumes the current file has been added to the Aider context."
(if-let ((function-name (which-function)))
(let* ((initial-prompt
(format "In the current file, analyze function '%s' using bottom-up reading approach.
Explain its basic operations, data structures, and control flow." function-name))
(user-input (aider-read-string "Enter analysis instructions: " initial-prompt)))
;; File context is added by aider-code-read
(aider--send-command (format "/ask %s" user-input) t))
(message "No function at point.")))
(defun aider--analyze-code-unit-region ()
"Analyze selected region using bottom-up reading technique."
(let* ((region-text (buffer-substring-no-properties (region-beginning) (region-end)))
(initial-prompt
"Analyze this code unit using bottom-up reading:
1. Identify basic operations and control structures
2. Explain data structures used
3. Document function calls and their purposes
4. Summarize the overall logic")
(user-input (aider-read-string "Enter analysis instructions: " initial-prompt)))
;; Sends region directly, doesn't add file context automatically
(aider--send-command (format "/ask %s\n\nCode:\n%s" user-input region-text) t)))
(defun aider--analyze-program-structure ()
"Analyze code structure using top-down reading technique.
Assumes the current file has been added to the Aider context."
(let* ((initial-prompt
"Please analyze the structure of the code in the current file using top-down reading:
1. Identify main components and their relationships
2. Explain the program's architecture (as represented in this file)
3. Document key interfaces between components within this file
4. Highlight important design patterns used
5. Map the control flow between major components in this file")
(user-input (aider-read-string "Enter structure analysis instructions: " initial-prompt)))
;; File context is added by aider-code-read
(aider--send-command (format "/ask %s" user-input) t)))
(defun aider--analyze-dependencies ()
"Analyze code dependencies following cross-reference technique.
Assumes the current file has been added to the Aider context."
(if-let ((function-name (which-function)))
(let* ((initial-prompt
(format "In the current file, analyze dependencies for function '%s':
1. List all functions it calls (within this file and potentially others if known)
2. List all functions within this file that call it
3. Identify key data dependencies (variables, parameters, return values)
4. Map external library dependencies used by this function
5. Note any global state interactions" function-name))
(user-input (aider-read-string "Enter dependency analysis instructions: " initial-prompt)))
;; File context is added by aider-code-read
(aider--send-command (format "/ask %s" user-input) t))
(message "No function at point.")))
(defun aider--identify-patterns ()
"Identify common patterns in code following pattern recognition approach.
Assumes the current file has been added to the Aider context."
(let* ((initial-prompt
"In the current file, please identify and explain:
1. Common design patterns used
2. Algorithmic patterns
3. Error handling patterns
4. Data structure patterns
5. Any anti-patterns or code smells that should be noted")
(user-input (aider-read-string "Enter pattern analysis instructions: " initial-prompt)))
;; File context is added by aider-code-read
(aider--send-command (format "/ask %s" user-input) t)))
(defun aider--analyze-class ()
"Analyze class definition using OOP analysis technique.
Assumes the current file has been added to the Aider context."
(if-let ((class-name (aider--get-class-at-point)))
(let* ((initial-prompt
(format "In the current file, analyze class '%s' using OOP perspective:
1. Class responsibility and purpose
2. Inheritance hierarchy and relationships (if applicable within the file)
3. Key attributes and their purposes
4. Public interface and method contracts
5. Internal implementation patterns
6. Collaboration with other classes (within the file)
7. State management approach" class-name))
(user-input (aider-read-string "Enter class analysis instructions: " initial-prompt)))
;; File context is added by aider-code-read
(aider--send-command (format "/ask %s" user-input) t))
(message "No class definition at point.")))
(defun aider--analyze-file ()
"Analyze current file using file-level reading technique.
Assumes the current file has been added to the Aider context."
(let* ((file-name (buffer-file-name))
(initial-prompt
(format "Analyze the entire file '%s' from a file-level perspective:
1. File's primary purpose and responsibilities
2. Key abstractions defined in the file (classes, functions, modules)
3. Dependencies and imports analysis
4. File organization and structure
5. Coding conventions used
6. Integration points with other files (if inferrable)
7. Configuration and environment dependencies mentioned
8. Notable algorithms or business logic contained within" (file-name-nondirectory file-name)))
(user-input (aider-read-string "Enter file analysis instructions: " initial-prompt)))
;; File context is added by aider-code-read
(aider--send-command (format "/ask %s" user-input) t)))
(defun aider--analyze-module ()
"Analyze a specified module/directory using architectural reading technique.
Adds the specified directory read-only to Aider before asking for analysis details."
(let* ((dir-name (read-directory-name "Enter module directory to analyze: " nil nil t)) ; t for mustmatch
(formatted-dir (aider--format-file-path (aider--get-file-path dir-name))))
;; Add the directory read-only first
(aider--send-command (format "/read-only %s" formatted-dir) nil)
;; Now proceed with asking the user
(let* ((initial-prompt
(format "The directory '%s' has been added read-only.
Analyze the module represented by this directory using an architectural perspective:
1. Module's likely role in the overall system.
2. Package organization and structure observed.
3. Key components and their interactions.
4. External dependencies and interfaces used.
5. Internal module architecture patterns observed.
6. Configuration management hints.
7. Testing strategy hints (e.g., presence of test files).
8. Integration patterns with other modules.
9. Deployment considerations mentioned." (file-name-as-directory dir-name))) ; Use file-name-as-directory for consistent trailing slash
(user-input (aider-read-string "Enter module analysis instructions: " initial-prompt)))
;; Send the analysis command
(aider--send-command (format "/ask %s" user-input) t))))
(defun aider--plot-module-architecture ()
"Analyze a module/directory and generate a DOT graph representation.
Adds the specified directory read-only to Aider before asking for analysis details."
(let* ((dir-name (read-directory-name "Enter module directory to plot: " nil nil t)) ; t for mustmatch
(formatted-dir (aider--format-file-path (aider--get-file-path dir-name))))
;; Add the directory read-only first
(aider--send-command (format "/read-only %s" formatted-dir) nil)
;; Now proceed with asking the user
(let* ((initial-prompt
(format "The directory '%s' has been added read-only.
Please analyze the architecture of the module within this directory and generate an ASCII art diagram representing the structure.
Focus on:
1. **Key Components:** Identify the main classes, modules, or significant functions. Represent these clearly as boxes or nodes in the ASCII diagram.
2. **Relationships/Connectors:** Show the primary interactions between components (e.g., calls, dependencies) using lines or arrows (`->`, `--`, `<-`). Label connections where clarity is needed.
3. **Layout:** Arrange the diagram logically to show dependencies and structure (e.g., top-down, left-to-right flow if applicable). Keep it reasonably compact.
4. **Clarity:** Use standard ASCII characters (`+`, `-`, `|`, `/`, `\`) to draw the diagram. Ensure it's readable in a fixed-width font environment.
Generate *only* the ASCII art diagram."
(file-name-as-directory dir-name))) ; Use file-name-as-directory for consistent trailing slash
(user-input (aider-read-string "Enter ASCII diagram generation instructions: " initial-prompt))) ; Changed prompt text
;; Send the analysis command
(aider--send-command (format "/ask %s" user-input) t))))
;; --- New Functions for Specific Concerns ---
(defun aider--analyze-for-security ()
"Analyze the current file for potential security vulnerabilities.
Assumes the current file has been added to the Aider context."
(let* ((initial-prompt
"Please analyze the code in the current file for potential security vulnerabilities:
1. Input Validation: Are inputs properly sanitized and validated? (e.g., against injection, path traversal)
2. Output Encoding: Is output properly encoded for its context? (e.g., HTML, SQL)
3. Authentication/Authorization: Are there checks missing or implemented insecurely?
4. Session Management: Are sessions handled securely?
5. Sensitive Data Exposure: Is sensitive data handled, stored, or logged insecurely?
6. Error Handling: Do error messages reveal too much information?
7. Dependency Security: Are there known vulnerabilities in used libraries (if inferrable)?
8. Concurrency Issues: Are there potential race conditions or deadlocks?")
(user-input (aider-read-string "Enter security analysis instructions: " initial-prompt)))
;; File context is added by aider-code-read
(aider--send-command (format "/ask %s" user-input) t)))
(defun aider--analyze-for-performance ()
"Analyze the current file for potential performance bottlenecks.
Assumes the current file has been added to the Aider context."
(let* ((initial-prompt
"Please analyze the code in the current file for potential performance bottlenecks:
1. Algorithmic Complexity: Are there algorithms with high complexity (e.g., O(n^2)) in critical paths?
2. Loops: Are there inefficient loops (e.g., excessive work inside, redundant computations)?
3. I/O Operations: Is I/O performed inefficiently (e.g., too frequently, large data transfers)?
4. Data Structures: Are appropriate data structures used for the operations performed?
5. Memory Usage: Are there signs of excessive memory allocation or potential memory leaks?
6. Concurrency: Are there potential performance issues related to locking or resource contention?
7. Caching: Are there opportunities for caching results that are missed?
8. Database Interaction: Are database queries potentially inefficient (e.g., N+1 problem)?")
(user-input (aider-read-string "Enter performance analysis instructions: " initial-prompt)))
;; File context is added by aider-code-read
(aider--send-command (format "/ask %s" user-input) t)))
(defun aider--analyze-for-maintainability ()
"Analyze the current file for code quality and maintainability issues.
Assumes the current file has been added to the Aider context."
(let* ((initial-prompt
"Please analyze the code in the current file for maintainability and code quality:
1. Readability: Is the code clear, well-formatted, and easy to understand? Are variable/function names meaningful?
2. Complexity: Are functions/methods too long or complex (high cyclomatic complexity)? Are classes too large (violating SRP)?
3. Duplication: Is there significant duplicated code (potential for DRY principle violation)?
4. Code Smells: Are there common code smells (e.g., magic numbers, feature envy, inappropriate intimacy)?
5. Comments/Documentation: Is the code adequately commented? Is documentation (e.g., docstrings) present and accurate?
6. Testability: Is the code structured in a way that makes it easy to write unit tests (e.g., low coupling, dependency injection)?
7. Consistency: Is the code style consistent throughout the file?
8. Modularity: Is the code well-modularized with clear responsibilities?")
(user-input (aider-read-string "Enter maintainability analysis instructions: " initial-prompt)))
;; File context is added by aider-code-read
(aider--send-command (format "/ask %s" user-input) t)))
;; --- Helper Functions (Unchanged) ---
(defun aider--get-class-at-point ()
"Get the class name at point. Support multiple programming languages."
(save-excursion
(let ((case-fold-search nil))
(when (re-search-backward "\\<\\(class\\|interface\\|trait\\|struct\\)\\s-+\\([A-Za-z0-9_]+\\)" nil t)
(match-string-no-properties 2)))))
(provide 'aider-code-read)
;;; aider-code-read.el ends here