Skip to content

Commit 75c657f

Browse files
authored
Merge pull request #4 from monch1962/clojure-tool-detector-refactoring
Refactor Clojure tool detector into modular architecture
2 parents 778e709 + 584b384 commit 75c657f

10 files changed

Lines changed: 2055 additions & 6 deletions

File tree

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
#!/usr/bin/env node
2+
/**
3+
* Clojure Tool Detector - Refactored Version
4+
*
5+
* Detect Clojure tools, versions, and project configuration
6+
* Supports Clojure CLI (deps.edn), Leiningen (project.clj), and Boot (build.boot)
7+
*
8+
* Refactored into modular architecture for better maintainability
9+
*/
10+
11+
// Import all modules
12+
const CoreDetector = require('./tool-detector-modules/core-detector');
13+
const BuildSystemDetector = require('./tool-detector-modules/build-system-detector');
14+
const ToolingDetector = require('./tool-detector-modules/tooling-detector');
15+
const FrameworkDetector = require('./tool-detector-modules/framework-detector');
16+
const ProjectParser = require('./tool-detector-modules/project-parser');
17+
const ReportGenerator = require('./tool-detector-modules/report-generator');
18+
const UtilityHelper = require('./tool-detector-modules/utility-helper');
19+
20+
class ClojureToolDetectorRefactored {
21+
constructor(projectPath = process.cwd()) {
22+
this.projectPath = projectPath;
23+
24+
// Initialize all modules
25+
this.coreDetector = new CoreDetector(projectPath);
26+
this.buildSystemDetector = new BuildSystemDetector(projectPath);
27+
this.toolingDetector = new ToolingDetector(projectPath);
28+
this.frameworkDetector = new FrameworkDetector(projectPath);
29+
this.projectParser = new ProjectParser(projectPath);
30+
this.reportGenerator = new ReportGenerator();
31+
this.utilityHelper = new UtilityHelper(projectPath);
32+
33+
// Cache for detected tools
34+
this.detectedTools = null;
35+
}
36+
37+
/**
38+
* Detect all Clojure tools and versions
39+
*/
40+
async detectTools() {
41+
if (this.detectedTools) {
42+
return this.detectedTools;
43+
}
44+
45+
// Detect core runtime components
46+
const java = await this.coreDetector.detectJava();
47+
const clojure = await this.coreDetector.detectClojure();
48+
const leiningen = await this.coreDetector.detectLeiningen();
49+
const boot = await this.coreDetector.detectBoot();
50+
51+
// Detect build system and project
52+
const buildSystem = await this.buildSystemDetector.detectBuildSystem();
53+
let project = await this.buildSystemDetector.detectProject();
54+
55+
// Parse project files if they exist
56+
const depsEdnPath = require('path').join(this.projectPath, 'deps.edn');
57+
const projectCljPath = require('path').join(this.projectPath, 'project.clj');
58+
59+
if (require('fs').existsSync(depsEdnPath)) {
60+
project = await this.projectParser.parseDepsEdn(depsEdnPath, project);
61+
}
62+
63+
if (require('fs').existsSync(projectCljPath)) {
64+
project = await this.projectParser.parseProjectClj(projectCljPath, project);
65+
}
66+
67+
// Detect tooling
68+
const linters = await this.toolingDetector.detectLinters();
69+
const formatters = await this.toolingDetector.detectFormatters();
70+
const testFrameworks = await this.toolingDetector.detectTestFrameworks();
71+
72+
// Detect frameworks and REPL
73+
const frameworks = await this.frameworkDetector.detectFrameworks();
74+
const repl = await this.frameworkDetector.detectRepl();
75+
const clojurescript = await this.frameworkDetector.detectClojureScript();
76+
77+
// Combine all tools
78+
const tools = {
79+
java,
80+
clojure,
81+
leiningen,
82+
boot,
83+
buildSystem,
84+
project,
85+
linters,
86+
formatters,
87+
testFrameworks,
88+
frameworks,
89+
repl,
90+
clojurescript,
91+
};
92+
93+
this.detectedTools = tools;
94+
return tools;
95+
}
96+
97+
/**
98+
* Detect Java runtime
99+
*/
100+
async detectJava() {
101+
return this.coreDetector.detectJava();
102+
}
103+
104+
/**
105+
* Detect Clojure CLI tools
106+
*/
107+
async detectClojure() {
108+
return this.coreDetector.detectClojure();
109+
}
110+
111+
/**
112+
* Detect Leiningen build tool
113+
*/
114+
async detectLeiningen() {
115+
return this.coreDetector.detectLeiningen();
116+
}
117+
118+
/**
119+
* Detect Boot build tool
120+
*/
121+
async detectBoot() {
122+
return this.coreDetector.detectBoot();
123+
}
124+
125+
/**
126+
* Detect build system from project files
127+
*/
128+
async detectBuildSystem() {
129+
return this.buildSystemDetector.detectBuildSystem();
130+
}
131+
132+
/**
133+
* Detect project type and configuration
134+
*/
135+
async detectProject() {
136+
let project = await this.buildSystemDetector.detectProject();
137+
138+
// Parse project files if they exist
139+
const depsEdnPath = require('path').join(this.projectPath, 'deps.edn');
140+
const projectCljPath = require('path').join(this.projectPath, 'project.clj');
141+
142+
if (require('fs').existsSync(depsEdnPath)) {
143+
project = await this.projectParser.parseDepsEdn(depsEdnPath, project);
144+
}
145+
146+
if (require('fs').existsSync(projectCljPath)) {
147+
project = await this.projectParser.parseProjectClj(projectCljPath, project);
148+
}
149+
150+
return project;
151+
}
152+
153+
/**
154+
* Parse deps.edn file
155+
*/
156+
async parseDepsEdn(depsEdnPath, projectInfo) {
157+
return this.projectParser.parseDepsEdn(depsEdnPath, projectInfo);
158+
}
159+
160+
/**
161+
* Parse project.clj file
162+
*/
163+
async parseProjectClj(projectCljPath, projectInfo) {
164+
return this.projectParser.parseProjectClj(projectCljPath, projectInfo);
165+
}
166+
167+
/**
168+
* Count list items in lines starting from index
169+
*/
170+
countListItems(lines, startIndex) {
171+
return this.utilityHelper.countListItems(lines, startIndex);
172+
}
173+
174+
/**
175+
* Extract list values from lines
176+
*/
177+
extractListValues(lines, startIndex) {
178+
return this.utilityHelper.extractListValues(lines, startIndex);
179+
}
180+
181+
/**
182+
* Check if project is a library
183+
*/
184+
isLibraryProject(projectInfo) {
185+
return this.utilityHelper.isLibraryProject(projectInfo);
186+
}
187+
188+
/**
189+
* Check if project is an application
190+
*/
191+
isApplicationProject(projectInfo) {
192+
return this.utilityHelper.isApplicationProject(projectInfo);
193+
}
194+
195+
/**
196+
* Detect linters
197+
*/
198+
async detectLinters() {
199+
return this.toolingDetector.detectLinters();
200+
}
201+
202+
/**
203+
* Detect formatters
204+
*/
205+
async detectFormatters() {
206+
return this.toolingDetector.detectFormatters();
207+
}
208+
209+
/**
210+
* Detect test frameworks
211+
*/
212+
async detectTestFrameworks() {
213+
return this.toolingDetector.detectTestFrameworks();
214+
}
215+
216+
/**
217+
* Detect frameworks
218+
*/
219+
async detectFrameworks() {
220+
return this.frameworkDetector.detectFrameworks();
221+
}
222+
223+
/**
224+
* Detect REPL configuration
225+
*/
226+
async detectRepl() {
227+
return this.frameworkDetector.detectRepl();
228+
}
229+
230+
/**
231+
* Detect ClojureScript configuration
232+
*/
233+
async detectClojureScript() {
234+
return this.frameworkDetector.detectClojureScript();
235+
}
236+
237+
/**
238+
* Get command path using which/where
239+
*/
240+
async getCommandPath(command) {
241+
return this.utilityHelper.getCommandPath(command);
242+
}
243+
244+
/**
245+
* Generate environment report
246+
*/
247+
generateEnvironmentReport(tools) {
248+
return this.reportGenerator.generateEnvironmentReport(tools);
249+
}
250+
251+
/**
252+
* Get project type description
253+
*/
254+
getProjectTypeDescription(project) {
255+
return this.reportGenerator.getProjectTypeDescription(project);
256+
}
257+
258+
/**
259+
* Get installation commands for missing tools
260+
*/
261+
getInstallationCommands(tools) {
262+
return this.reportGenerator.getInstallationCommands(tools);
263+
}
264+
}
265+
266+
module.exports = ClojureToolDetectorRefactored;

languages/clojure/config-wizard.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77

88
const path = require('path');
9-
const ClojureToolDetector = require('./tool-detector');
9+
const ClojureToolDetector = require('./clojure-tool-detector-refactored');
1010

1111
class ClojureConfigWizard {
1212
constructor(projectPath = process.cwd()) {
@@ -395,7 +395,7 @@ class ClojureConfigWizard {
395395
console.log(' • Windows: Use Windows Subsystem for Linux (WSL)');
396396
console.log(' • Or use install script:');
397397
console.log(
398-
' curl -O https://download.clojure.org/install/linux-install-1.11.1.1347.sh',
398+
' curl -O https://download.clojure.org/install/linux-install-1.11.1.1347.sh'
399399
);
400400
console.log(' chmod +x linux-install-1.11.1.1347.sh');
401401
console.log(' sudo ./linux-install-1.11.1.1347.sh');
@@ -405,7 +405,7 @@ class ClojureConfigWizard {
405405
console.log(' Install Leiningen:');
406406
console.log(' • Download lein script:');
407407
console.log(
408-
' curl -O https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein',
408+
' curl -O https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein'
409409
);
410410
console.log(' • Make it executable:');
411411
console.log(' chmod +x lein');
@@ -419,7 +419,7 @@ class ClojureConfigWizard {
419419
console.log(' Install clj-kondo:');
420420
console.log(' • Using install script:');
421421
console.log(
422-
' bash <(curl -s https://raw.githubusercontent.com/clj-kondo/clj-kondo/master/script/install-clj-kondo)',
422+
' bash <(curl -s https://raw.githubusercontent.com/clj-kondo/clj-kondo/master/script/install-clj-kondo)'
423423
);
424424
console.log(' • Or download binary from:');
425425
console.log(' https://github.com/clj-kondo/clj-kondo/releases');
@@ -429,7 +429,7 @@ class ClojureConfigWizard {
429429
console.log(' Install zprint:');
430430
console.log(' • Using install script:');
431431
console.log(
432-
' curl -s https://raw.githubusercontent.com/kkinnear/zprint/main/install | bash',
432+
' curl -s https://raw.githubusercontent.com/kkinnear/zprint/main/install | bash'
433433
);
434434
console.log(' • Or as a CLI tool:');
435435
console.log(' clojure -Ttools install-latest :lib io.github.kkinnear/zprint :as zprint');

0 commit comments

Comments
 (0)