diff --git a/pom.xml b/pom.xml index 7ca14d6..22f0753 100644 --- a/pom.xml +++ b/pom.xml @@ -179,11 +179,6 @@ langchain4j 0.34.0 - - com.github.javaparser - javaparser-core - 3.24.0 - org.json json diff --git a/src/main/java/io/github/jeddict/ai/JavaCompletionProvider.java b/src/main/java/io/github/jeddict/ai/JavaCompletionProvider.java index 5c92680..9332387 100644 --- a/src/main/java/io/github/jeddict/ai/JavaCompletionProvider.java +++ b/src/main/java/io/github/jeddict/ai/JavaCompletionProvider.java @@ -18,7 +18,6 @@ */ package io.github.jeddict.ai; -import static com.github.javaparser.utils.Utils.trimTrailingSpaces; import io.github.jeddict.ai.scanner.MyTreePathScanner; import com.sun.source.tree.ClassTree; import java.util.*; @@ -80,6 +79,7 @@ import static io.github.jeddict.ai.util.MimeUtil.JAVA_MIME; import static io.github.jeddict.ai.util.StringUtil.removeAllSpaces; import static io.github.jeddict.ai.util.StringUtil.trimLeadingSpaces; +import static io.github.jeddict.ai.util.StringUtil.trimTrailingSpaces; import java.io.OutputStream; import java.io.PrintWriter; import org.netbeans.api.editor.completion.Completion; diff --git a/src/main/java/io/github/jeddict/ai/fix/JavaDocFixImpl.java b/src/main/java/io/github/jeddict/ai/fix/JavaDocFixImpl.java index febb82d..4acfdf7 100644 --- a/src/main/java/io/github/jeddict/ai/fix/JavaDocFixImpl.java +++ b/src/main/java/io/github/jeddict/ai/fix/JavaDocFixImpl.java @@ -19,15 +19,9 @@ package io.github.jeddict.ai.fix; import io.github.jeddict.ai.util.StringUtil; -import com.github.javaparser.JavaParser; -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; -import com.github.javaparser.ast.body.FieldDeclaration; -import com.github.javaparser.ast.body.MethodDeclaration; -import com.github.javaparser.ast.comments.JavadocComment; import com.sun.source.doctree.DocCommentTree; import com.sun.source.doctree.DocTree; -import com.sun.source.tree.ClassTree; +import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.MethodTree; import com.sun.source.tree.Tree; import static com.sun.source.tree.Tree.Kind.CLASS; @@ -40,16 +34,15 @@ import io.github.jeddict.ai.Action; import io.github.jeddict.ai.JeddictChatModel; import static io.github.jeddict.ai.Action.ENHANCE; -import static io.github.jeddict.ai.util.FileUtil.saveOpenEditor; +import static io.github.jeddict.ai.util.SourceUtil.geIndentaion; import static io.github.jeddict.ai.util.StringUtil.removeCodeBlockMarkers; import static io.github.jeddict.ai.util.StringUtil.trimLeadingSpaces; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.LinkedList; import java.util.List; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; import org.netbeans.api.java.source.ElementHandle; import org.netbeans.api.java.source.JavaSource; import org.netbeans.api.java.source.TreeMaker; @@ -86,140 +79,107 @@ protected String getText() { @Override protected void performRewrite(JavaFix.TransformationContext tc) throws Exception { - WorkingCopy copy = tc.getWorkingCopy(); - if (copy.toPhase(JavaSource.Phase.RESOLVED).compareTo(JavaSource.Phase.RESOLVED) < 0) { + WorkingCopy wc = tc.getWorkingCopy(); + if (wc.toPhase(JavaSource.Phase.RESOLVED).compareTo(JavaSource.Phase.RESOLVED) < 0) { return; } - saveOpenEditor(); TreePath treePath = tc.getPath(); - Tree leaf = treePath.getLeaf(); - Element elm = copy.getTrees().getElement(treePath); + Tree tree = treePath.getLeaf(); + Element elm = wc.getTrees().getElement(treePath); if (elm == null) { return; } + Document document = wc.getDocument(); + String javadocContent; - DocCommentTree oldDocCommentTree = ((DocTrees) copy.getTrees()).getDocCommentTree(treePath); + DocCommentTree oldDocCommentTree = wc.getDocTrees().getDocCommentTree(treePath); - switch (leaf.getKind()) { + switch (tree.getKind()) { case CLASS: case INTERFACE: if (action == ENHANCE) { - javadocContent = new JeddictChatModel().enhanceJavadocForClass(oldDocCommentTree.toString(), leaf.toString()); + javadocContent = new JeddictChatModel().enhanceJavadocForClass(oldDocCommentTree.toString(), tree.toString()); } else { - javadocContent = new JeddictChatModel().generateJavadocForClass(leaf.toString()); + javadocContent = new JeddictChatModel().generateJavadocForClass(tree.toString()); } break; case METHOD: if (action == ENHANCE) { - javadocContent = new JeddictChatModel().enhanceJavadocForMethod(oldDocCommentTree.toString(), ((MethodTree) leaf).getName().toString()); + javadocContent = new JeddictChatModel().enhanceJavadocForMethod(oldDocCommentTree.toString(), ((MethodTree) tree).getName().toString()); } else { - javadocContent = new JeddictChatModel().generateJavadocForMethod(((MethodTree) leaf).getName().toString()); + javadocContent = new JeddictChatModel().generateJavadocForMethod(((MethodTree) tree).getName().toString()); } break; case VARIABLE: if (action == ENHANCE) { - javadocContent = new JeddictChatModel().enhanceJavadocForField(oldDocCommentTree.toString(), ((VariableTree) leaf).getName().toString()); + javadocContent = new JeddictChatModel().enhanceJavadocForField(oldDocCommentTree.toString(), ((VariableTree) tree).getName().toString()); } else { - javadocContent = new JeddictChatModel().generateJavadocForField(((VariableTree) leaf).getName().toString()); + javadocContent = new JeddictChatModel().generateJavadocForField(((VariableTree) tree).getName().toString()); } break; default: return; } + javadocContent = removeCodeBlockMarkers(javadocContent); - Path filePath = Paths.get(copy.getFileObject().toURI()); + if (action == ENHANCE && oldDocCommentTree != null && document != null) { + DocTrees docTrees = wc.getDocTrees(); + CompilationUnitTree cuTree = wc.getCompilationUnit(); - String sourceCode = new String(Files.readAllBytes(filePath)); - JavaParser javaParser = new JavaParser(); - CompilationUnit cu = javaParser.parse(sourceCode).getResult().orElse(null); + long start = docTrees.getSourcePositions().getStartPosition(cuTree, oldDocCommentTree, oldDocCommentTree); + long end = docTrees.getSourcePositions().getEndPosition(cuTree, oldDocCommentTree, oldDocCommentTree); - if (cu == null) { - return; - } + int startPos = (int) start; + int endPos = (int) end; - // Add the Javadoc comment to the appropriate location - switch (leaf.getKind()) { - case CLASS: - case INTERFACE: - String className = ((ClassTree) leaf).getSimpleName().toString(); - cu.findFirst(ClassOrInterfaceDeclaration.class) - .filter(decl -> decl.getNameAsString().equals(className)) - .ifPresent(classDecl -> { - JavadocComment comment = new JavadocComment(removeCodeBlockMarkers(javadocContent)); - classDecl.setComment(comment); - }); - break; - case METHOD: - MethodTree methodTree = (MethodTree) leaf; - String methodName = methodTree.getName().toString(); - - cu.findFirst(ClassOrInterfaceDeclaration.class).ifPresent(classDecl -> { - classDecl.findAll(MethodDeclaration.class).stream() - .filter(methodDecl -> methodDecl.getNameAsString().equals(methodName)) - .findFirst() - .ifPresent(methodDecl -> { - JavadocComment comment = new JavadocComment(removeCodeBlockMarkers(javadocContent)); - methodDecl.setComment(comment); - }); - }); - break; - case VARIABLE: - cu.findFirst(FieldDeclaration.class).ifPresent(fieldDecl -> { - fieldDecl.getVariables().forEach(varDecl -> { - if (varDecl.getNameAsString().equals(((VariableTree) leaf).getName().toString())) { - JavadocComment comment = new JavadocComment(removeCodeBlockMarkers(javadocContent)); - fieldDecl.setComment(comment); - } - }); - }); - break; - default: - return; - } + try { + // Search for '*/' after the end position of the current comment + String content = document.getText(endPos, document.getLength() - endPos); + int afterEndPos = content.indexOf("*/") + endPos + 2; // Position after the '*/' - // Write the modified code back to the file - String modifiedCode = cu.toString(); - Files.write(filePath, modifiedCode.getBytes()); - } + // Search for '/**' before the start position of the current comment + content = document.getText(0, startPos); + int beforeStartPos = content.lastIndexOf("/**"); - private void updateJavadoc(WorkingCopy copy, TreePath treePath, TreeMaker make, String javadocContent, ElementKind elementKind) { - List firstSentence = new LinkedList<>(); - List tags = new LinkedList<>(); - List body = new LinkedList<>(); - boolean ci = treePath.getLeaf().getKind() == Tree.Kind.CLASS || treePath.getLeaf().getKind() == Tree.Kind.INTERFACE; - - // Split the content into lines for simulation - String[] lines = javadocContent.split("\n"); - for (String line : lines) { - line = trimLeadingSpaces(line); - if (line.startsWith("/**") || line.startsWith("*/")) { - } else if (line.startsWith("* @")) { - tags.add(make.Text(line.substring(1))); - } else if (line.startsWith("*") || line.isEmpty()) { - if (line.startsWith("*")) { - firstSentence.add(make.Text(line.substring(1))); - if (ci) { - firstSentence.add(make.Text("\n * ")); + // Remove all space until a newline character is found before '/**' + while (beforeStartPos > 0 && content.charAt(beforeStartPos) != '\n') { + beforeStartPos--; // Move backward to include spaces before the newline + } + + // Remove the entire Javadoc, from 'beforeStartPos' to 'afterEndPos' + if (beforeStartPos >= 0 && afterEndPos > beforeStartPos) { // Ensure valid positions + document.remove(beforeStartPos, afterEndPos - beforeStartPos); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + int startOffset = (int) wc.getTrees().getSourcePositions() + .getStartPosition(wc.getCompilationUnit(), tree); + + if (document != null) { + String lastLine = geIndentaion(wc, tree); + if (lastLine.isBlank() && lastLine.length() <= 12) { + StringBuilder indentedContent = new StringBuilder(); + boolean ignore = true; + for (String line : javadocContent.split("\n")) { + if (ignore) { + ignore = false; + indentedContent.append(line).append("\n").append(lastLine); } else { - firstSentence.add(make.Text("\n * ")); + indentedContent.append(line).append("\n").append(lastLine); } - } else if (line.isEmpty()) { - firstSentence.add(make.Text("")); } + javadocContent = indentedContent.toString(); + } else { + javadocContent = javadocContent + '\n'; } + document.insertString(startOffset, javadocContent, null); } - if (!firstSentence.isEmpty() && firstSentence.get(firstSentence.size() - 1).toString().equals("\n * ")) { - firstSentence.remove(firstSentence.size() - 1); - } - if (!firstSentence.isEmpty() && firstSentence.get(firstSentence.size() - 1).toString().equals("\n * ")) { - firstSentence.remove(firstSentence.size() - 1); - } - - DocCommentTree oldDocCommentTree = ((DocTrees) copy.getTrees()).getDocCommentTree(treePath); - DocCommentTree newDocCommentTree = make.DocComment(firstSentence, body, tags); - copy.rewrite(treePath.getLeaf(), oldDocCommentTree, newDocCommentTree); + } } diff --git a/src/main/java/io/github/jeddict/ai/fix/MethodFix.java b/src/main/java/io/github/jeddict/ai/fix/MethodFix.java index 17483fd..d430a82 100644 --- a/src/main/java/io/github/jeddict/ai/fix/MethodFix.java +++ b/src/main/java/io/github/jeddict/ai/fix/MethodFix.java @@ -4,8 +4,6 @@ */ package io.github.jeddict.ai.fix; -import com.github.javaparser.JavaParser; -import com.github.javaparser.ast.CompilationUnit; import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.MethodTree; import com.sun.source.tree.Tree; @@ -15,11 +13,9 @@ import io.github.jeddict.ai.JeddictChatModel; import io.github.jeddict.ai.util.SourceUtil; import static io.github.jeddict.ai.util.FileUtil.saveOpenEditor; +import static io.github.jeddict.ai.util.SourceUtil.geIndentaion; import static io.github.jeddict.ai.util.StringUtil.removeCodeBlockMarkers; import static io.github.jeddict.ai.util.UIUtil.askQuery; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import javax.lang.model.element.Element; import org.json.JSONArray; import org.json.JSONObject; @@ -28,7 +24,6 @@ import org.netbeans.api.java.source.TreeMaker; import org.netbeans.api.java.source.TreePathHandle; import org.netbeans.api.java.source.WorkingCopy; -import org.netbeans.modules.editor.indent.api.Reformat; import org.netbeans.spi.java.hints.JavaFix; import org.openide.util.NbBundle; @@ -99,13 +94,7 @@ protected void performRewrite(JavaFix.TransformationContext tc) throws Exception } } - Path filePath = Paths.get(copy.getFileObject().toURI()); - - String sourceCode = new String(Files.readAllBytes(filePath)); - JavaParser javaParser = new JavaParser(); - CompilationUnit cu = javaParser.parse(sourceCode).getResult().orElse(null); - - if (cu == null || content == null) { + if (content == null) { return; } @@ -137,9 +126,7 @@ protected void performRewrite(JavaFix.TransformationContext tc) throws Exception } // Formating - int startPos = (int) copy.getTrees().getSourcePositions().getStartPosition(copy.getCompilationUnit(), leaf); - String[] lines = sourceCode.substring(0, startPos).split("\n"); // Zero-based index - String lastLine = lines[lines.length - 1]; + String lastLine = geIndentaion(copy, leaf); if (lastLine.isBlank() && lastLine.length() <= 12) { StringBuilder indentedContent = new StringBuilder(); boolean ignore = true; @@ -156,5 +143,7 @@ protected void performRewrite(JavaFix.TransformationContext tc) throws Exception copy.rewrite(leaf, copy.getTreeMaker().QualIdent(methodContent)); } + + } diff --git a/src/main/java/io/github/jeddict/ai/fix/RestEndpointFix.java b/src/main/java/io/github/jeddict/ai/fix/RestEndpointFix.java index 2e89b89..68421ba 100644 --- a/src/main/java/io/github/jeddict/ai/fix/RestEndpointFix.java +++ b/src/main/java/io/github/jeddict/ai/fix/RestEndpointFix.java @@ -4,10 +4,6 @@ */ package io.github.jeddict.ai.fix; -import com.github.javaparser.JavaParser; -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.body.MethodDeclaration; -import com.github.javaparser.ast.visitor.VoidVisitorAdapter; import com.sun.source.tree.ClassTree; import com.sun.source.tree.Tree; import static com.sun.source.tree.Tree.Kind.CLASS; @@ -18,11 +14,6 @@ import io.github.jeddict.ai.util.SourceUtil; import static io.github.jeddict.ai.util.FileUtil.saveOpenEditor; import static io.github.jeddict.ai.util.StringUtil.removeCodeBlockMarkers; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Formatter; import javax.lang.model.element.Element; import org.json.JSONArray; import org.json.JSONObject; diff --git a/src/main/java/io/github/jeddict/ai/util/JavaParserUtil.java b/src/main/java/io/github/jeddict/ai/util/JavaParserUtil.java deleted file mode 100644 index 0c8b7a9..0000000 --- a/src/main/java/io/github/jeddict/ai/util/JavaParserUtil.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.github.jeddict.ai.util; - -import com.github.javaparser.JavaParser; -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; -import com.github.javaparser.ast.body.MethodDeclaration; -import com.sun.source.tree.MethodTree; -import org.json.JSONArray; - -/** - * - * @author Gaurav Gupta - */ -public class JavaParserUtil { - - public static void addImports(CompilationUnit cu, JSONArray imports) { - for (int i = 0; i < imports.length(); i++) { - String imp = imports.getString(i).trim(); // Trim any extra spaces - - if (!imp.isEmpty()) { - String className; - if (imp.startsWith("import ") && imp.endsWith(";")) { - className = imp.substring(7, imp.length() - 1).trim(); // Extract the class name - } else { - className = imp; - } - - boolean alreadyImported = cu.getImports().stream() - .anyMatch(existingImport -> existingImport.getNameAsString().equals(className)); - if (!alreadyImported) { - cu.addImport(className); - } - } - } - } - - public static void addMethods(CompilationUnit cu, JSONArray methods, JavaParser javaParser) { - cu.findFirst(ClassOrInterfaceDeclaration.class).ifPresent(classDecl -> { - for (int i = 0; i < methods.length(); i++) { - String methodCode = methods.getString(i); - if (!methodCode.trim().isEmpty()) { - MethodDeclaration methodDeclaration = javaParser.parseMethodDeclaration(methodCode.trim()).getResult().orElse(null); - if (methodDeclaration != null) { - classDecl.addMember(methodDeclaration); - } - } - } - }); - } - - public static void updateMethods(CompilationUnit cu, MethodTree methodTree, JSONArray imports, String javaSnippet, JavaParser javaParser) { - String methodName = methodTree.getName().toString(); - - cu.findFirst(ClassOrInterfaceDeclaration.class).ifPresent(classDecl -> { - // Find and remove the original method by its name - classDecl.findFirst(MethodDeclaration.class, method -> method.getNameAsString().equals(methodName)) - .ifPresent(classDecl::remove); - StringBuilder importsBuilder = new StringBuilder(); - for (int i = 0; i < imports.length(); i++) { - String importStatement = imports.getString(i); - if (importStatement.startsWith("import")) { - importsBuilder.append(importStatement); - } else { - importsBuilder.append("import ").append(importStatement).append(";\n"); - } - } - String wrappedSnippet = importsBuilder.toString() // Appending the imports - + "public class TempClass {\n" + javaSnippet + "\n}"; - javaParser.parse(wrappedSnippet).getResult().ifPresent(parsed -> { - // Iterate through all types in the parsed snippet - parsed.getTypes().forEach(type -> { - if (type instanceof ClassOrInterfaceDeclaration) { - ClassOrInterfaceDeclaration tempClass = (ClassOrInterfaceDeclaration) type; - - // Add each field (variable) found in the parsed snippet - tempClass.getFields().forEach(newField -> { - classDecl.addMember(newField); - }); - - // Add each method found in the parsed snippet - tempClass.getMethods().forEach(newMethod -> { - classDecl.addMember(newMethod); - }); - } - }); - }); - }); - } - -} diff --git a/src/main/java/io/github/jeddict/ai/util/SourceUtil.java b/src/main/java/io/github/jeddict/ai/util/SourceUtil.java index a5ec786..17fbe39 100644 --- a/src/main/java/io/github/jeddict/ai/util/SourceUtil.java +++ b/src/main/java/io/github/jeddict/ai/util/SourceUtil.java @@ -21,11 +21,16 @@ import com.sun.source.tree.ClassTree; import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.ImportTree; +import com.sun.source.tree.Tree; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; +import javax.swing.text.BadLocationException; import org.json.JSONArray; import org.netbeans.api.java.source.JavaSource; import org.netbeans.api.java.source.TreeMaker; @@ -108,4 +113,19 @@ public static void reformatClass(WorkingCopy copy, ClassTree classTree) throws E // Alternatively, save changes and let the IDE apply auto-format on save if configured } + + public static String geIndentaion(WorkingCopy copy, Tree leaf) { + try { + if (copy.getDocument() != null) { + String sourceCode = copy.getDocument().getText(0, copy.getDocument().getEndPosition().getOffset()); + int startPos = (int) copy.getTrees().getSourcePositions().getStartPosition(copy.getCompilationUnit(), leaf); + String[] lines = sourceCode.substring(0, startPos).split("\n"); // Zero-based index + String lastLine = lines[lines.length - 1]; + return lastLine; + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + return ""; + } } diff --git a/src/main/java/io/github/jeddict/ai/util/StringUtil.java b/src/main/java/io/github/jeddict/ai/util/StringUtil.java index 7aceeae..3b44184 100644 --- a/src/main/java/io/github/jeddict/ai/util/StringUtil.java +++ b/src/main/java/io/github/jeddict/ai/util/StringUtil.java @@ -54,9 +54,9 @@ public static String removeCodeBlockMarkers(String input) { input = content.trim(); } input = input.trim(); - if (input.startsWith("/**") && input.endsWith("*/")) { - input = input.substring(3, input.length() - 2).trim(); - } +// if (input.startsWith("/**") && input.endsWith("*/")) { +// input = input.substring(3, input.length() - 2).trim(); +// } return input; // Return the original input if it does not match the expected format }