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 "void 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 "void add(int index, E element)"`) to prevent shell syntax errors.

---

## <a id="contributing"></a>🤝 Contributing
Expand Down
23 changes: 13 additions & 10 deletions docs/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@
You have a tool called `jfocus` installed in system PATH.
When user asks for Java code analysis, refactoring, or explanation:

1. **Analysis Strategy**:
- DO NOT read the entire file content blindly.
- ALWAYS use `jfocus <file> <method>` to extract the context first.
- Use `-v` flag ONLY when you need to see dependency implementation details.
1. **Analysis Strategy (Tool Selection)**:
- **For Method-Level Logic:** ALWAYS use `jfocus <file> <method>` to extract the context. This saves tokens and focuses on the specific logic. Use `-v` flag ONLY when you need to see dependency implementation details.
- **For Class-Level Structure/Fields:** If the user asks about class fields, annotations, or overall architecture, you MAY read the file directly using standard tools (like `cat`), but try to run `jfocus <file> -l` first to grasp the method outline.

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.
- `jfocus <file> <method>` : Extracts context for the method.
- If JFocus returns a "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 `void add(int index, E element)`), you MUST wrap the method name in quotes to prevent Bash syntax errors.
Comment on lines +10 to +16

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

Fix the article before the error name.

Use “a” instead of “an” before “Multiple overloads found.”

✏️ Proposed doc tweak
-  - If JFocus returns an "Multiple overloads found" error, it will also print the exact available signatures. You MUST retry using the EXACT signature.
+  - If JFocus returns a "Multiple overloads found" error, it will also print the exact available signatures. You MUST retry using the EXACT signature.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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 `void add(int index, E element)`), you MUST wrap the method name in quotes to prevent Bash syntax errors.
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 a "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 `void add(int index, E element)`), you MUST wrap the method name in quotes to prevent Bash syntax errors.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/rules.md` around lines 11 - 16, Change the indefinite article before the
error name "Multiple overloads found" from "an" to "a" in the Command Usage
(CRITICAL) section; specifically update the sentence that currently reads 'If
JFocus returns an "Multiple overloads found" error...' to read 'If JFocus
returns a "Multiple overloads found" error...'; also scan the same document for
any other occurrences of the exact error string and correct their articles to
"a" as well.

- Correct: `jfocus MyClass "void add(int index, E element)"`
- Incorrect: `jfocus MyClass void 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**.
- Do **NOT** assume missing methods or fields exist.
- If context seems incomplete, explicitly use `jfocus -v` to check dependencies.
- When using `jfocus <file> <method>`, treat its output as the source of truth **for that specific method and its dependencies**.
- However, remember that `jfocus` extracts specific targets; do NOT falsely assume the class lacks fields or other methods just because they are omitted from the targeted output.

4. **Execution**: Run the command, assume the output is the ground truth context, and answer based on it.
4. **Execution**: Run the command appropriate for the user's intent, analyze the output, and answer based on it.
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
40 changes: 35 additions & 5 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, true) + "\"");
}
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 @@ -127,9 +146,7 @@ private MethodDeclaration selectMethodInteractive(CompilationUnit cu) {
System.err.println("\nAvailable Methods:");
for (int i = 0; i < allMethods.size(); i++) {
MethodDeclaration m = allMethods.get(i);
// Format: [1] methodName(paramType paramName)
String params = m.getParameters().toString().replace("[", "(").replace("]", ")");
System.err.printf(" [%d] %s%s\n", i + 1, m.getNameAsString(), params);
System.err.printf(" [%d] %s\n", i + 1, m.getDeclarationAsString(false, false, true));
}

while (true) {
Expand Down Expand Up @@ -160,8 +177,7 @@ private MethodDeclaration selectMethodInteractive(List<MethodDeclaration> method
System.err.println("\nAvailable Methods:");
for (int i = 0; i < methods.size(); i++) {
MethodDeclaration m = methods.get(i);
String params = m.getParameters().toString().replace("[", "(").replace("]", ")");
System.err.printf(" [%d] %s%s\n", i + 1, m.getNameAsString(), params);
System.err.printf(" [%d] %s\n", i + 1, m.getDeclarationAsString(false, false, true));
}
while (true) {
System.err.print("\nSelect method number (or 'q' to quit): ");
Expand Down Expand Up @@ -196,4 +212,18 @@ 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) {
System.out.println("- " + m.getDeclarationAsString(false, false, true));
}
}
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