Skip to content
5 changes: 4 additions & 1 deletion README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,14 +259,15 @@ jfocus
### CLI 옵션 (Options)

```bash
Usage: jfocus [-cvhV] [fileName] [methodName]
Usage: jfocus [-clvhV] [fileName] [methodName]
```

| 옵션 | 설명 | 예시 |
|------|------|------|
| `[fileName]` | 분석할 자바 파일명 (확장자 생략 가능) | `UserController` |
| `[methodName]` | 분석할 메서드명 | `login` |
| `-c`, `--copy` | 결과를 터미널에 출력하는 대신 **클립보드에 복사**합니다. | `jfocus -c` |
| `-l`, `--list` | 대화형 프롬프트 없이 **사용 가능한 메서드 목록을 출력**하고 정상 종료합니다. | `jfocus UserController -l` |
| `-v`, `--verbose` | **직접 참조된** 다른 메서드의 소스 코드를 포함합니다. (깊은 재귀 탐색 제외) | `jfocus -v` |
| `-h`, `--help` | 도움말 메시지를 표시합니다. | |
| `-V`, `--version` | 버전 정보를 표시합니다. | |
Expand Down Expand Up @@ -376,6 +377,8 @@ Usage: jfocus [-cvhV] [fileName] [methodName]

에이전트는 자동으로 `jfocus`를 실행하여 문맥을 파악한 뒤, 정확한 답변을 제공할 것입니다.

> **오버로딩 메서드 주의사항:** 오버로딩된 메서드를 분석할 때 매개변수를 지정해야 한다면 (예: `add(int, E)`), 셸 문법 오류를 방지하기 위해 에이전트가 정확한 시그니처를 **반드시 따옴표로 감싸도록** (예: `jfocus MyClass "add(int index, E element)"`) 규칙을 설정해 주세요.

---

## <a id="contributing"></a>🤝 기여하기 (Contributing)
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,15 @@ jfocus
### CLI Options

```bash
Usage: jfocus [-cvhV] [fileName] [methodName]
Usage: jfocus [-clvhV] [fileName] [methodName]
```

| Option | Description | Example |
|------|------|------|
| `[fileName]` | Java filename to analyze (extension optional) | `UserController` |
| `[methodName]` | Method name to analyze | `login` |
| `-c`, `--copy` | **Copies result to clipboard** instead of printing to terminal. | `jfocus -c` |
| `-l`, `--list` | **Lists available methods** without interactive prompt and cleanly exits. | `jfocus UserController -l` |
| `-v`, `--verbose` | Includes source code of **Directly Referenced** methods. (Excludes deep recursive search) | `jfocus -v` |
| `-h`, `--help` | Show help message. | |
| `-V`, `--version` | Show version information. | |
Expand Down Expand Up @@ -370,6 +371,8 @@ Now ask the agent naturally:

The agent will automatically run `jfocus`, grasp the context, and provide an accurate response.

> **Note on Overloaded Methods:** If a method requires specifying parameters to resolve an overload (e.g. `add(int, E)`), be sure to configure the agent to wrap the exact signature in quotes (e.g., `jfocus MyClass "add(int index, E element)"`) to prevent shell syntax errors.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Documented signature format doesn't match the actual matching logic.

The example jfocus MyClass "add(int index, E element)" includes parameter names. However, extractMethods in MethodExtractor.java matches via:

  • getDeclarationAsString(false, false, false) → produces void add(int, E) (return type + param types only, no param names)
  • getSignature().asString() → produces add(int, E) (no return type, no param names)

Neither matches "add(int index, E element)", so the documented usage won't resolve the overload. See the root-cause comment on MethodExtractor.java for a proposed fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 374 - 375, The README example uses parameter names
but MethodExtractor.extractMethods matches signatures using
getDeclarationAsString(false,false,false) or getSignature().asString(), which
produce forms like "void add(int, E)" or "add(int, E)"; update the documented
example to show the actual matching format (e.g., jfocus MyClass "add(int, E)"
or include return type "void add(int, E)") or change
MethodExtractor.extractMethods to normalize/accept parameter names; reference
MethodExtractor.extractMethods, getDeclarationAsString(false, false, false), and
getSignature().asString() when making the change so the doc and matching logic
align.

---

## <a id="contributing"></a>🤝 Contributing
Expand Down
9 changes: 7 additions & 2 deletions docs/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@ When user asks for Java code analysis, refactoring, or explanation:
- ALWAYS use `jfocus <file> <method>` to extract the context first.
- Use `-v` flag ONLY when you need to see dependency implementation details.

2. **Command Usage**:
- `jfocus <file>` : Lists available methods in the file.
2. **Command Usage (CRITICAL)**:
- **NEVER use `jfocus <file>` without `-l` or a method name.** It triggers an interactive prompt that will cause you (the agent) to hang/timeout.
- `jfocus <file> -l` : Lists available methods in the file non-interactively. Always use this instead of reading the entire file to save tokens.
- `jfocus <file> <method>` : Extracts context for the method.
- If JFocus returns an "Multiple overloads found" error, it will also print the exact available signatures. You MUST retry using the EXACT signature.
- **CRITICAL:** When specifying an exact method signature with parameters (like `add(int index, E element)`), you MUST wrap the method name in quotes to prevent Bash syntax errors.
- Correct: `jfocus MyClass "add(int index, E element)"`
- Incorrect: `jfocus MyClass add(int index, E element)`
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

3. **Trust Model**:
- Treat JFocus output as the **ONLY source of truth**.
Expand Down
2 changes: 1 addition & 1 deletion scripts/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ $Version = "1.0.0" # Release version
$JarName = "j-focus-$Version-all.jar"
$InstallDir = "$HOME\.jfocus"
# Checksum for security (SHA256) - Paste the hash from Step 1 here!
$ExpectedSha256 = "64d38039c8731215635e8b501af9963b3721dfeebfac609ff95b9e0bc7c7309f"
$ExpectedSha256 = "373a6b1bf44f9c58bd31953368c59ecfd130820b6c8615a887752c329f38f89b"

$DownloadUrl = "https://github.com/$Repo/releases/download/v$Version/$JarName"
$DestPath = "$InstallDir\j-focus.jar"
Expand Down
2 changes: 1 addition & 1 deletion scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ VERSION="1.0.0" # Release version
JAR_NAME="j-focus-${VERSION}-all.jar"
INSTALL_DIR="$HOME/.jfocus"
# Checksum for security (SHA256) - Paste the hash here!
EXPECTED_SHA256="64d38039c8731215635e8b501af9963b3721dfeebfac609ff95b9e0bc7c7309f"
EXPECTED_SHA256="373a6b1bf44f9c58bd31953368c59ecfd130820b6c8615a887752c329f38f89b"

DOWNLOAD_URL="https://github.com/$REPO/releases/download/v$VERSION/$JAR_NAME"

Expand Down
34 changes: 34 additions & 0 deletions src/main/java/com/jher235/jfocus/cli/JFocusCli.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public class JFocusCli implements Callable<Integer> {
private boolean verbose;
@Option(names = { "-c", "--copy" }, description = "Copy to clipboard instead of stdout")
private boolean copyToClipboard;
@Option(names = { "-l", "--list" }, description = "List all available methods without interactive prompt")
private boolean listMode;

public static void main(String[] args) {
int exitCode = new CommandLine(new JFocusCli()).execute(args);
Expand Down Expand Up @@ -64,6 +66,11 @@ public Integer call() {
String foundPath = cu.getStorage().map(s -> s.getPath().toString()).orElse("Unknown");
System.err.println("Found File: " + foundPath);

if (listMode) {
printMethodList(cu);
return 0;
}

// 3. Handle Method Selection
MethodDeclaration targetMethod;
if (methodName == null) {
Expand All @@ -77,6 +84,18 @@ public Integer call() {
return 1;
}
if (methods.size() > 1) {
boolean isInteractive = System.console() != null;
if (!isInteractive) {
System.err.println("[Error] Multiple overloads found for method '" + methodName + "'.");
System.err.println(
"In non-interactive mode, you MUST specify the exact signature wrapped in quotes.");
System.err.println("\nAvailable signatures:");
for (MethodDeclaration m : methods) {
System.err.println("- \"" + m.getDeclarationAsString(false, false, false) + "\"");
}
System.err.println("\nExiting. (Exit code 1)");
return 1;
}
System.err.println("Multiple overloads found. Please choose: ");
targetMethod = selectMethodInteractive(methods);
} else {
Expand Down Expand Up @@ -196,4 +215,19 @@ private void copyToClipboard(String content) {
System.out.println(content);
}
}

private void printMethodList(CompilationUnit cu) {
List<MethodDeclaration> allMethods = cu.findAll(MethodDeclaration.class);

if (allMethods.isEmpty()) {
System.err.println("No methods found in this file.");
return;
}

System.out.println("Available Methods:");
for (MethodDeclaration m : allMethods) {
String params = m.getParameters().toString().replace("[", "(").replace("]", ")");
System.out.println("- " + m.getNameAsString() + params);
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
10 changes: 6 additions & 4 deletions src/main/java/com/jher235/jfocus/core/MethodExtractor.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,22 @@ public class MethodExtractor {
/**
* Finds all methods matching the specified name (case-insensitive).
*
* @param cu The parsed CompilationUnit.
* @param cu The parsed CompilationUnit.
* @param methodName The name of the method to find.
* @return A list of matching MethodDeclarations.
*/
public List<MethodDeclaration> extractMethods(CompilationUnit cu, String methodName) {
return cu.findAll(MethodDeclaration.class).stream()
.filter(method -> method.getNameAsString().equalsIgnoreCase(methodName))
.toList();
.filter(method -> method.getNameAsString().equalsIgnoreCase(methodName) ||
method.getDeclarationAsString(false, false, false).equals(methodName) ||
method.getSignature().asString().equals(methodName))
.toList();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

/**
* Extracts the source code of the found methods into a single string.
*
* @param cu The parsed CompilationUnit.
* @param cu The parsed CompilationUnit.
* @param methodName The name of the method to extract.
* @return An Optional containing the combined source code of the methods.
*/
Expand Down