-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #332 from devoxx/feat-327
Feat #327 : POC of TDG
- Loading branch information
Showing
26 changed files
with
260 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/main/java/com/devoxx/genie/service/tdg/ClassNameNotFoundException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.devoxx.genie.service.tdg; | ||
|
||
public class ClassNameNotFoundException extends Exception { | ||
public ClassNameNotFoundException(String message) { | ||
super(message); | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
src/main/java/com/devoxx/genie/service/tdg/CodeContainer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.devoxx.genie.service.tdg; | ||
|
||
import lombok.EqualsAndHashCode; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
import lombok.ToString; | ||
|
||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
@ToString | ||
@EqualsAndHashCode | ||
@Setter | ||
@Getter | ||
public final class CodeContainer { | ||
|
||
private final String content; | ||
private final String fileName; | ||
private final String packageName; | ||
private final int attempts; | ||
|
||
public CodeContainer(String content) throws ClassNameNotFoundException { | ||
this(content, 1); | ||
} | ||
|
||
public CodeContainer(String content, int attempts) throws ClassNameNotFoundException { | ||
this.content = content; | ||
this.fileName = extractClassName() + ".java"; | ||
this.packageName = extractPackageName(); | ||
this.attempts = attempts; | ||
} | ||
|
||
// TODO: first look for 'public class' and then for 'class | ||
private String extractClassName() throws ClassNameNotFoundException { | ||
// matches "public" (optional) followed by "class" and then the class name | ||
String regex = "\\b(?:public\\s+)?class\\s+(\\w+)\\b"; | ||
Matcher matcher = Pattern.compile(regex).matcher(content); | ||
if (matcher.find()) { | ||
return matcher.group(1); | ||
} else { | ||
throw new ClassNameNotFoundException("Class name not found in: " + content); | ||
} | ||
} | ||
|
||
private String extractPackageName() { | ||
String regex = "package\\s+(\\w+(\\.\\w+)*)"; | ||
Matcher matcher = Pattern.compile(regex).matcher(content); | ||
if (matcher.find()) { | ||
return matcher.group(1); | ||
} else { | ||
return ""; | ||
} | ||
} | ||
} |
128 changes: 128 additions & 0 deletions
128
src/main/java/com/devoxx/genie/service/tdg/CodeGeneratorService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package com.devoxx.genie.service.tdg; | ||
|
||
import com.devoxx.genie.model.request.ChatMessageContext; | ||
import com.devoxx.genie.ui.util.NotificationUtil; | ||
import com.intellij.openapi.application.ApplicationManager; | ||
import com.intellij.openapi.application.ModalityState; | ||
import com.intellij.openapi.fileEditor.FileEditorManager; | ||
import com.intellij.openapi.module.Module; | ||
import com.intellij.openapi.module.ModuleManager; | ||
import com.intellij.openapi.progress.ProgressIndicator; | ||
import com.intellij.openapi.progress.Task; | ||
import com.intellij.openapi.project.Project; | ||
import com.intellij.openapi.roots.ModuleRootManager; | ||
import com.intellij.openapi.vfs.VirtualFile; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import java.io.IOException; | ||
import java.nio.charset.StandardCharsets; | ||
|
||
public class CodeGeneratorService { | ||
|
||
public static void createClassFromCodeSnippet(@NotNull ChatMessageContext chatMessageContext, | ||
String selectedText) { | ||
Project project = chatMessageContext.getProject(); | ||
|
||
new Task.Backgroundable(project, "Creating java class", false) { | ||
@Override | ||
public void run(@NotNull ProgressIndicator indicator) { | ||
try { | ||
indicator.setIndeterminate(true); | ||
indicator.setText("Parsing code..."); | ||
|
||
CodeContainer codeContainer = new CodeContainer(selectedText); | ||
String packageName = codeContainer.getPackageName(); | ||
String fileName = codeContainer.getFileName(); | ||
|
||
indicator.setText("Creating class file..."); | ||
|
||
ApplicationManager.getApplication().invokeAndWait(() -> | ||
ApplicationManager.getApplication().runWriteAction(() -> | ||
createFile(packageName, fileName, project, selectedText)), | ||
ModalityState.defaultModalityState()); | ||
|
||
} catch (Exception e) { | ||
NotificationUtil.sendNotification(project, | ||
"Error creating class: " + e.getMessage()); | ||
} | ||
} | ||
}.queue(); | ||
} | ||
|
||
private static void createFile(String packageName, | ||
String fileName, | ||
Project project, | ||
String selectedText) { | ||
try { | ||
// Find the proper source root for Java files | ||
VirtualFile sourceRoot = findSourceRoot(project); | ||
if (sourceRoot == null) { | ||
NotificationUtil.sendNotification(project, | ||
"Error: Could not find source root directory"); | ||
return; | ||
} | ||
|
||
VirtualFile packageDir = createPackageDirectories(sourceRoot, packageName); | ||
VirtualFile existingFile = packageDir.findChild(fileName); | ||
VirtualFile javaFile; | ||
|
||
if (existingFile != null) { | ||
existingFile.setBinaryContent( | ||
selectedText.getBytes(StandardCharsets.UTF_8)); | ||
javaFile = existingFile; | ||
NotificationUtil.sendNotification(project, | ||
"Class updated successfully"); | ||
} else { | ||
javaFile = packageDir.createChildData(null, fileName); | ||
javaFile.setBinaryContent( | ||
selectedText.getBytes(StandardCharsets.UTF_8)); | ||
NotificationUtil.sendNotification(project, | ||
"Class created successfully"); | ||
} | ||
|
||
FileEditorManager.getInstance(project).openFile(javaFile, true); | ||
|
||
} catch (IOException e) { | ||
NotificationUtil.sendNotification(project, | ||
"Error creating class: " + e.getMessage()); | ||
} | ||
} | ||
|
||
private static @Nullable VirtualFile findSourceRoot(Project project) { | ||
ModuleManager moduleManager = ModuleManager.getInstance(project); | ||
for (Module module : moduleManager.getModules()) { | ||
ModuleRootManager rootManager = ModuleRootManager.getInstance(module); | ||
// Get source roots for the module | ||
for (VirtualFile root : rootManager.getSourceRoots(false)) { | ||
// Look for the main source root, typically ending with "src/main/java" | ||
if (root.getPath().endsWith("src/main/java")) { | ||
return root; | ||
} | ||
} | ||
// Fallback to first source root if we can't find main/java | ||
VirtualFile[] sourceRoots = rootManager.getSourceRoots(false); | ||
if (sourceRoots.length > 0) { | ||
return sourceRoots[0]; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
private static VirtualFile createPackageDirectories(@NotNull VirtualFile sourceRoot, | ||
@NotNull String packageName) throws IOException { | ||
if (packageName.isEmpty()) { | ||
return sourceRoot; | ||
} | ||
|
||
VirtualFile currentDir = sourceRoot; | ||
for (String part : packageName.split("\\.")) { | ||
VirtualFile subDir = currentDir.findChild(part); | ||
if (subDir == null) { | ||
subDir = currentDir.createChildDirectory(null, part); | ||
} | ||
currentDir = subDir; | ||
} | ||
return currentDir; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.