Skip to content

Commit 22fc0e6

Browse files
committed
fix windows path
1 parent 8b7827b commit 22fc0e6

File tree

5 files changed

+86
-25
lines changed

5 files changed

+86
-25
lines changed

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.1.2] - 2024-05-30
9+
10+
### 🐛 Bug Fixes
11+
- **Windows Path Compatibility**: Fixed cross-platform path handling issues
12+
- **Test Directory Detection**: Enhanced `isTestDirectory()` to normalize Windows backslashes to forward slashes
13+
- **Production/Test Code Classification**: Fixed `isProductionCode()` and `isTestCode()` methods to handle Windows paths
14+
- **Source File Path Resolution**: Updated `getSourceFilePathForClass()` to use `Path.resolve()` instead of hardcoded path strings
15+
- **Root Cause**: Previous implementation only handled Unix-style paths (`/`), causing "No test source roots found" on Windows
16+
- **Solution**: Added path normalization (`pathString.replace('\\', '/')`) throughout path comparison logic
17+
18+
### 🔧 Technical Details
19+
- Modified `ParseTestCaseToLlmContextTask.isTestDirectory()` method
20+
- Enhanced `TestCaseAnalyzer.isProductionCode()` and `isTestCode()` methods
21+
- Updated `TestCaseAnalyzer.getSourceFilePathForClass()` to use proper `Path.resolve()` chains
22+
- All path comparisons now use normalized forward slash format internally
23+
- Maintains full backward compatibility on Unix/Linux/macOS systems
24+
25+
### 🌍 Cross-Platform Support
26+
-**Windows**: Now correctly identifies test directories like `D:\project\src\test\java`
27+
-**Unix/Linux**: Continues to work with `/project/src/test/java`
28+
-**macOS**: Continues to work with `/project/src/test/java`
29+
830
## [1.1.1] - 2024-05-30
931

1032
### 🐛 Bug Fixes

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ application {
1717
}
1818

1919
group = 'edu.stevens'
20-
version = '1.1.1'
20+
version = '1.1.2'
2121

2222
dependencies {
2323
// Use JitPack dependency for release builds

src/main/java/edu/stevens/swe/research/java/cli/Main.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import edu.stevens.swe.research.java.cli.analyzer.TaskResult;
1616
import edu.stevens.swe.research.java.cli.analyzer.ResultFormatter;
1717

18-
@Command(name = "analyzer", mixinStandardHelpOptions = true, version = "Analyzer CLI 1.1.1",
18+
@Command(name = "analyzer", mixinStandardHelpOptions = true, version = "Analyzer CLI 1.1.2",
1919
description = "Analyzes Java source code based on specified tasks.")
2020
public class Main implements Callable<Integer> {
2121

src/main/java/edu/stevens/swe/research/java/cli/analyzer/core/TestCaseAnalyzer.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -390,12 +390,16 @@ private String getSpace(int count) {
390390
// Heuristics to determine if a path is production or test code.
391391
// These should ideally be configurable or more robustly determined from ProjectCtx.
392392
private boolean isProductionCode(String filePath) {
393-
return filePath.contains(File.separator + "src" + File.separator + "main" + File.separator) ||
394-
!filePath.contains(File.separator + "src" + File.separator + "test" + File.separator); // Assume prod if not explicitly test
393+
// Normalize path separators for cross-platform compatibility
394+
String normalizedPath = filePath.replace('\\', '/');
395+
return normalizedPath.contains("/src/main/") ||
396+
!normalizedPath.contains("/src/test/"); // Assume prod if not explicitly test
395397
}
396398

397399
private boolean isTestCode(String filePath) {
398-
return filePath.contains(File.separator + "src" + File.separator + "test" + File.separator);
400+
// Normalize path separators for cross-platform compatibility
401+
String normalizedPath = filePath.replace('\\', '/');
402+
return normalizedPath.contains("/src/test/");
399403
}
400404

401405
// Utility from old MethodAnalyzer to find source file for a class.
@@ -407,11 +411,11 @@ public String getSourceFilePathForClass(String className, String sourceRootPath)
407411
// Attempt to find in standard main/java or test/java if sourceRootPath is project root
408412
// This is a heuristic. ProjectCtx should ideally provide specific source roots.
409413
List<Path> potentialSourceRoots = new ArrayList<>();
410-
if (Files.isDirectory(effectiveSourceRoot.resolve("src/main/java"))) {
411-
potentialSourceRoots.add(effectiveSourceRoot.resolve("src/main/java"));
414+
if (Files.isDirectory(effectiveSourceRoot.resolve("src").resolve("main").resolve("java"))) {
415+
potentialSourceRoots.add(effectiveSourceRoot.resolve("src").resolve("main").resolve("java"));
412416
}
413-
if (Files.isDirectory(effectiveSourceRoot.resolve("src/test/java"))) {
414-
potentialSourceRoots.add(effectiveSourceRoot.resolve("src/test/java"));
417+
if (Files.isDirectory(effectiveSourceRoot.resolve("src").resolve("test").resolve("java"))) {
418+
potentialSourceRoots.add(effectiveSourceRoot.resolve("src").resolve("test").resolve("java"));
415419
}
416420
// If no sub-source roots found, use the provided sourceRootPath directly
417421
if (potentialSourceRoots.isEmpty()) {

src/main/java/edu/stevens/swe/research/java/cli/analyzer/tasks/ParseTestCaseToLlmContextTask.java

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -166,28 +166,48 @@ private boolean isTestMethod(MethodDeclaration md) {
166166
private List<Path> findAllTestDirectories(Path projectRoot) {
167167
List<Path> testDirectories = new ArrayList<>();
168168

169+
System.out.println("DEBUG: Starting directory search from: " + projectRoot);
170+
System.out.println("DEBUG: Project root exists: " + Files.exists(projectRoot));
171+
System.out.println("DEBUG: Project root is directory: " + Files.isDirectory(projectRoot));
172+
System.out.println("DEBUG: Project root is readable: " + Files.isReadable(projectRoot));
173+
174+
// Check if basic src/test/java structure exists
175+
Path srcTestJava = projectRoot.resolve("src").resolve("test").resolve("java");
176+
System.out.println("DEBUG: Standard test path: " + srcTestJava);
177+
System.out.println("DEBUG: Standard test path exists: " + Files.exists(srcTestJava));
178+
System.out.println("DEBUG: Standard test path is directory: " + Files.isDirectory(srcTestJava));
179+
169180
try (Stream<Path> paths = Files.walk(projectRoot)) {
170181
List<Path> candidateDirectories = paths.filter(Files::isDirectory)
171182
.filter(this::isTestDirectory)
172183
.collect(java.util.stream.Collectors.toList());
173184

185+
System.out.println("DEBUG: Found " + candidateDirectories.size() + " candidate test directories");
186+
for (Path candidate : candidateDirectories) {
187+
System.out.println("DEBUG: Candidate: " + candidate);
188+
}
189+
174190
// Remove nested directories - only keep the most specific src/test/java directories
175191
for (Path candidate : candidateDirectories) {
176192
boolean isNested = false;
177193
for (Path other : candidateDirectories) {
178194
if (!candidate.equals(other) && candidate.startsWith(other)) {
179195
isNested = true;
196+
System.out.println("DEBUG: " + candidate + " is nested under " + other + ", skipping");
180197
break;
181198
}
182199
}
183200
if (!isNested) {
184201
testDirectories.add(candidate);
202+
System.out.println("DEBUG: Adding final test directory: " + candidate);
185203
}
186204
}
187205
} catch (IOException e) {
188206
System.err.println("Error walking project directory: " + e.getMessage());
207+
e.printStackTrace();
189208
}
190209

210+
System.out.println("DEBUG: Final test directories count: " + testDirectories.size());
191211
return testDirectories;
192212
}
193213

@@ -198,30 +218,44 @@ private boolean isTestDirectory(Path dir) {
198218
String dirName = dir.getFileName().toString();
199219
String pathString = dir.toString();
200220

221+
// Normalize path separators for cross-platform compatibility
222+
String normalizedPath = pathString.replace('\\', '/');
223+
224+
// Debug output for troubleshooting
225+
if (pathString.contains("test") && pathString.contains("java")) {
226+
System.out.println("DEBUG: Checking potential test directory: " + pathString);
227+
System.out.println("DEBUG: Normalized path: " + normalizedPath);
228+
System.out.println("DEBUG: Dir name: " + dirName);
229+
}
230+
201231
// Skip hidden directories and common non-source directories
202232
if (dirName.startsWith(".") ||
203-
pathString.contains("/.") ||
204-
pathString.contains("/target/") ||
205-
pathString.contains("/build/") ||
206-
pathString.contains("/bin/") ||
207-
pathString.contains("/out/") ||
208-
pathString.contains("/node_modules/") ||
209-
pathString.contains("/.git/") ||
210-
pathString.contains("/.gradle/") ||
211-
pathString.contains("/.m2/")) {
233+
normalizedPath.contains("/.") ||
234+
normalizedPath.contains("/target/") ||
235+
normalizedPath.contains("/build/") ||
236+
normalizedPath.contains("/bin/") ||
237+
normalizedPath.contains("/out/") ||
238+
normalizedPath.contains("/node_modules/") ||
239+
normalizedPath.contains("/.git/") ||
240+
normalizedPath.contains("/.gradle/") ||
241+
normalizedPath.contains("/.m2/")) {
242+
if (pathString.contains("test") && pathString.contains("java")) {
243+
System.out.println("DEBUG: Skipped due to filter: " + normalizedPath);
244+
}
212245
return false;
213246
}
214247

215-
// Standard Maven/Gradle test directory patterns
216-
if (pathString.endsWith("/src/test/java") ||
217-
pathString.endsWith("\\src\\test\\java")) {
248+
// Standard Maven/Gradle test directory patterns (cross-platform)
249+
if (normalizedPath.endsWith("/src/test/java")) {
250+
System.out.println("DEBUG: Found test directory (standard pattern): " + normalizedPath);
218251
return true;
219252
}
220253

221254
// Additional test directory patterns for different project structures
222255
// Be more specific to avoid false positives
223-
if (pathString.contains("/src/test/") && pathString.endsWith("/java") &&
224-
!pathString.contains("/build/") && !pathString.contains("/target/")) {
256+
if (normalizedPath.contains("/src/test/") && normalizedPath.endsWith("/java") &&
257+
!normalizedPath.contains("/build/") && !normalizedPath.contains("/target/")) {
258+
System.out.println("DEBUG: Found test directory (extended pattern): " + normalizedPath);
225259
return true;
226260
}
227261

@@ -231,8 +265,9 @@ private boolean isTestDirectory(Path dir) {
231265
if (parent != null && parent.getFileName().toString().equals("test")) {
232266
Path srcParent = parent.getParent();
233267
if (srcParent != null && srcParent.getFileName().toString().equals("src")) {
234-
// Ensure it's not in a build directory
235-
if (!pathString.contains("/build/") && !pathString.contains("/target/") && !pathString.contains("/bin/")) {
268+
// Ensure it's not in a build directory (using normalized path)
269+
if (!normalizedPath.contains("/build/") && !normalizedPath.contains("/target/") && !normalizedPath.contains("/bin/")) {
270+
System.out.println("DEBUG: Found test directory (multi-module pattern): " + normalizedPath);
236271
return true;
237272
}
238273
}

0 commit comments

Comments
 (0)