Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ java -version # Java 21 이상인지 확인

```bash
# ⚠️ 보안이 우려된다면 실행 전 스크립트 내용을 확인하세요.
curl -sL https://raw.githubusercontent.com/jher235/j-focus/main/scripts/install.sh | bash
curl -sL https://raw.githubusercontent.com/jher235/j-focus/develop/scripts/install.sh | bash
Comment thread
jher235 marked this conversation as resolved.
```

#### Windows (PowerShell)

관리자 권한 없이도 실행 가능합니다. 설치 후 환경 변수(PATH)까지 자동으로 설정합니다.

```powershell
iwr -useb https://raw.githubusercontent.com/jher235/j-focus/main/scripts/install.ps1 | iex
iwr -useb https://raw.githubusercontent.com/jher235/j-focus/develop/scripts/install.ps1 | iex
```

---
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ Automatically registers Alias for `jfocus` command along with installation.

```bash
# ⚠️ Review the install script before piping to bash if you have security concerns.
curl -sL https://raw.githubusercontent.com/jher235/j-focus/main/scripts/install.sh | bash
curl -sL https://raw.githubusercontent.com/jher235/j-focus/develop/scripts/install.sh | bash
Comment thread
jher235 marked this conversation as resolved.
```

#### Windows (PowerShell)

This script can be executed without administrator privileges. Automatically sets environment variables (PATH) after installation.

```powershell
iwr -useb https://raw.githubusercontent.com/jher235/j-focus/main/scripts/install.ps1 | iex
iwr -useb https://raw.githubusercontent.com/jher235/j-focus/develop/scripts/install.ps1 | iex
```

---
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 = "ab3c3e429e96460f1045986d69e42e7e6a85d31451ae658464129a8efcf00abd"
$ExpectedSha256 = "64d38039c8731215635e8b501af9963b3721dfeebfac609ff95b9e0bc7c7309f"

$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="ab3c3e429e96460f1045986d69e42e7e6a85d31451ae658464129a8efcf00abd"
EXPECTED_SHA256="64d38039c8731215635e8b501af9963b3721dfeebfac609ff95b9e0bc7c7309f"

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

Expand Down
9 changes: 2 additions & 7 deletions src/main/java/com/jher235/jfocus/cli/JFocusCli.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,7 @@
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;

@Command(
name = "jfocus",
mixinStandardHelpOptions = true,
version = "jfocus 1.0.0",
description = "Analyzes Java code context for LLM prompting."
)
@Command(name = "jfocus", mixinStandardHelpOptions = true, version = "jfocus 1.0.0", description = "Analyzes Java code context for LLM prompting.")
public class JFocusCli implements Callable<Integer> {

private final Scanner scanner = new Scanner(System.in);
Expand Down Expand Up @@ -96,7 +91,7 @@ public Integer call() {

// 4. Extract & Export
ContextExtractor contextExtractor = new ContextExtractor(projectParser);
ContextResult contextResult = contextExtractor.extractContext(targetMethod);
ContextResult contextResult = contextExtractor.extractContext(targetMethod, verbose);

MarkdownExporter.ExportConfig config = new MarkdownExporter.ExportConfig(verbose);
MarkdownExporter exporter = new MarkdownExporter(config);
Expand Down
44 changes: 32 additions & 12 deletions src/main/java/com/jher235/jfocus/core/ContextExtractor.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
* Orchestrates the extraction of code context.
* It uses DependencyResolver to find related nodes and categorizes them
* into internal (same class) and external (other classes) layers.
* Supports recursive analysis to capture the full call chain within the project.
* Supports recursive analysis to capture the full call chain within the
* project.
*/
public class ContextExtractor {

Expand All @@ -28,7 +29,18 @@ public ContextExtractor(ProjectParser projectParser) {
* @param targetMethod The method to analyze
* @return Categorized context (target + internal + external + fields)
*/
// Backward-compatible default: non-verbose (shallow)
public ContextResult extractContext(MethodDeclaration targetMethod) {
return extractContext(targetMethod, false);
}

/**
* @param verbose if true, recursively traverses internal methods to collect
* their external calls as well (deep mode).
* if false, only collects direct (1-depth) calls of the target
* method (shallow mode).
*/
public ContextResult extractContext(MethodDeclaration targetMethod, boolean verbose) {
ContextResult result = new ContextResult(targetMethod);

// Fields
Expand All @@ -38,25 +50,31 @@ public ContextResult extractContext(MethodDeclaration targetMethod) {
Set<String> visited = new HashSet<>();
visited.add(AstUtils.createMethodId(targetMethod));

// Start recursive analysis
extractRecursive(targetMethod, targetMethod, result, visited);
// shallow = !verbose: in shallow mode, stop recursing after the first level
extractRecursive(targetMethod, targetMethod, result, visited, !verbose);

return result;
}

/**
* Recursively traverses method calls to find all related user code.
* External libraries are automatically excluded as they lack source code definitions.
* Traverses method calls to collect related user code.
* External libraries are automatically excluded as they lack source code
* definitions.
*
* @param shallow if true, stops after the first level of calls (no further
* recursion).
* if false, recursively follows all dependencies.
*/
private void extractRecursive(MethodDeclaration rootTarget,
MethodDeclaration currentMethod,
ContextResult result,
Set<String> visited) {
MethodDeclaration currentMethod,
ContextResult result,
Set<String> visited,
boolean shallow) {

List<MethodDeclaration> dependencies = dependencyResolver.resolveMethods(currentMethod);

ClassOrInterfaceDeclaration rootClass = rootTarget.findAncestor(ClassOrInterfaceDeclaration.class)
.orElse(null);
.orElse(null);

for (MethodDeclaration dep : dependencies) {
String depId = AstUtils.createMethodId(dep);
Expand All @@ -69,7 +87,7 @@ private void extractRecursive(MethodDeclaration rootTarget,
visited.add(depId);

ClassOrInterfaceDeclaration depClass = dep.findAncestor(ClassOrInterfaceDeclaration.class)
.orElse(null);
.orElse(null);

// Categorize into Internal (same class) vs External (different class)
if (rootClass != null && rootClass.equals(depClass)) {
Expand All @@ -78,8 +96,10 @@ private void extractRecursive(MethodDeclaration rootTarget,
result.addExternalMethod(dep);
}

// Continue recursion to find deeper dependencies
extractRecursive(rootTarget, dep, result, visited);
// In shallow mode, do not recurse further beyond the first level
if (!shallow) {
extractRecursive(rootTarget, dep, result, visited, shallow);
}
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/main/java/com/jher235/jfocus/core/MarkdownExporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,8 @@ private void appendExternalContext(StringBuilder sb, ContextResult result) {
sb.append("Signatures and JavaDocs are provided to maintain focus.\n\n");

for (MethodDeclaration method : result.getExternalMethods()) {
// Include JavaDoc if present (toText() strips tags, toString() keeps them)
method.getJavadoc().ifPresent(javadoc ->
sb.append(javadoc.toString()).append("\n"));
// Include JavaDoc if present as clean text
method.getJavadoc().ifPresent(javadoc -> sb.append(javadoc.toText()).append("\n"));

// Include Signature only
String signature = method.getDeclarationAsString(true, true, true) + ";";
Expand Down