Java 1-14 Parser and Abstract Syntax Tree for Java, including preview features to Java 13.
Hi, Happy New Year everyone - I think I've found a new issue, I tried searching but didn't find anything that looked similar.
I encountered this when running against some code that makes use of log4j and has a call like this - logger.traceEntry("" + fee) - The fee variable is a double.
The log4j library has two trace methods that take a String and optional values, in this scenario javaparser throws an IndexOutOfBoundsException.
I've created a simple test - this class throws the exception:
`
public class AParserTest {
public void log() {
double fee = 0.1;
doSomething("" + fee);
}
private void doSomething(String string, Supplier<?>... supplier) {
}
private void doSomething(String format, Object... params) {
}
}This doesn't:
public class AParserTest {
public void log() {
double fee = 0.1;
doSomething("" + fee);
}
private void doSomething(String string, Supplier<?>... supplier) {
}
}
`
Javaparser is expecting to find a second argument in MethodResolutionLogic.isExactMatch but doesn't find one, because it's optional. I'm not doing anything fancy in the javaparser call, just calling resolve() on the MethodCallExpr.
Hi all - I think I have found an issue... java.io.File contains the overloaded method 'listFiles', one takes a FileFilter and the other a FilenameFilter, both of which are functional interfaces, the former taking a single File argument and the later taking File and String arguments.
When the parser sees a call like this, it struggles to work out which method is being called and throws a MethodAmbiguityException:
File[] newFilesToRegister = directory.listFiles((dir, name) -> {
...
}
The two arguments in the argument list for the lambda expression should allow the parser to determine which method is being called.
I see a closed issue #2775 that talks of a similar thing but was deployed in 3.16.2 - I'm using 3.18
If @jlerbsc has a kofi account, I'll buy him a coffee :-)
If @jlerbsc has a kofi account, I'll buy him a coffee :-)
Thank you. I'm just using JP in my work and I'm just trying here to spend some time to get to the community what this project brings. I think that's the spirit of open source. For the moment I am spending a few days of family vacation in Martinique (in the sun). I'm going to do a little pose ;-)
ResolvedReferenceTypeDeclaration
into a ResolvedReferenceType
or viceversa? If this question is more suitable as an issue, I can file one.
new ReferenceTypeImpl(resolvedReferenceTypeDeclaration, typeSolver)
, where typeSolver
is the CombinedTypeSolver
used to setup javaparser's configuration
VoidVisitorAdapter
to visit recursively multiple files and for each file print the relevant information. However, within the visit
method I would like to have access to the string of the file name so I can keep track of which file I am processing (add a column with file name in the output). In the github link above is the script and I also paste here the relevant part of code in case someone can help: @Command(name = "CodeSeq", version = "1.0.1", mixinStandardHelpOptions = true)
public class CodeSeq implements Runnable{
@Option(names = { "-o", "--output"}, description = "Output File and path.")
String outputFilePath = "./java_data.tsv";
@Option(names = { "-i", "--input"}, description = "Input Path to be recursively searched for .java files")
String RootPath = "/mnt/Data/scratch/";
@Override
public void run(){
try{
FileWriter outputFile = new FileWriter(outputFilePath);
outputFile.write("class\tclass_lines\tmethod\tmethod_lines\n");
try(Stream<Path> walk = Files.walk(Paths.get(RootPath))){
List<String> result = walk.map(x -> x.toString()).filter(f -> f.endsWith(".java")).collect(Collectors.toList());
for (String fileName : result) {
Path fileNamePath = Paths.get(fileName);
if (!Files.isRegularFile(fileNamePath)) {
continue;
}
FileInputStream f = new FileInputStream(fileName);
try {
CompilationUnit cu = StaticJavaParser.parse(f);
VoidVisitor<FileWriter> methodNamePrinter = new MethodNamePrinter();
methodNamePrinter.visit(cu, outputFile);
} catch (ParseProblemException e) {
System.out.println("Skipping file: " + fileName);
}
}
outputFile.close();
} catch(IOException e){
e.printStackTrace();
}
}catch(IOException ex){
System.out.println("Error writing to file");
ex.printStackTrace();
}
}
public static void main(String[] args){
int exitCode = new CommandLine(new CodeSeq()).execute(args);
System.exit(exitCode);
}
private static class MethodNamePrinter extends VoidVisitorAdapter<FileWriter> {
@Override
public void visit(ClassOrInterfaceDeclaration cl, FileWriter arg) {
super.visit(cl, arg);
Range class_range = cl.getRange().get();
int class_loc = Math.max(class_range.begin.line, class_range.end.line) - Math.min(class_range.begin.line, class_range.end.line) + 1;
for (MethodDeclaration method : cl.getMethods()) {
Range r = method.getRange().get();
int loc = Math.max(r.begin.line, r.end.line) - Math.min(r.begin.line, r.end.line) + 1;
try{
arg.write(cl.getName() + "\t" + class_loc + "\t" + method.getName() + "\t" + loc + "\n");
}catch(IOException ex){
System.out.println("Error writing to file");
}
}
}
}
}
Hi , How can i get fields those has annotations alone?
Finally was able to get it .Sharing the code here, may be useful for some one or please correct if anything is wrong
for (TypeDeclaration<?> typeDec : cu.getTypes()) {
for (BodyDeclaration<?> member : typeDec.getMembers()) {
member.toFieldDeclaration().ifPresent(field -> {
if(field.getAnnotations() != null && field.getAnnotations().size() > 0) {
System.out.println(field);
}
});
}
}
`
Hello Guys,
I am new to this library and I was trying to use CombinedTypeSolver to get method declarations from java source code,
but instead I got UnsuportedOperationException.
So here's what I did:
Here are some relevent code snippets:
This is where I call all the methods
@SpringBootTest
class SourceComponentTest {
@Autowired
private Parser parser;
private SourceComponent sourceComponent;
private static final String MULTIPLE_FILES_PATH = "src/test/testSources/JavaParserFacadeTests/testParserClass/MultipleFileTest/multipleFilesTest";
@BeforeEach
void setUp() {
var resolvedTypeList = parser.getAllResolvedDeclarations(MULTIPLE_FILES_PATH);
sourceComponent = new SourceComponent(resolvedTypeList);
}
//TODO: FINISH THIS!
@Test
public void TestToString() {
System.out.println(sourceComponent);
fail();
}
}
This How I parse each file.
@Bean
public DirExplorer dirExplorer(@Autowired VoidVisitor<List<String>> visitor) {
return new DirExplorer((level, path, file) -> file.getName().endsWith(".java"), (level, path, file, state) -> {
try {
JavaParser javaParser = javaParser();
CompilationUnit cu = javaParser.parse(file).getResult().get();
visitor.visit(cu, state);
} catch (FileNotFoundException e) {
throw new RuntimeException("[DirExplorer.FileHandler] File not found at: " + file.getAbsolutePath());
}
});
}
this returns a list of ResolvedDeclaraion.
public List<ResolvedDeclaration> getAllResolvedDeclarations(String PATH) {
CombinedTypeSolver typeSolver = new CombinedTypeSolver();
typeSolver.add(new JavaParserTypeSolver(PATH));
typeSolver.add(new ReflectionTypeSolver());
javaParser.getParserConfiguration()
.setSymbolResolver(new JavaSymbolSolver(typeSolver));
var classList = parseClasses(PATH);
List<ResolvedDeclaration> resolvedDeclarationList = new ArrayList<>();
classList.forEach(k -> resolvedDeclarationList.add(typeSolver.solveType(k)));
return resolvedDeclarationList;
}
This is where I get all the ResolvedMethodDeclarations.
private void generateParsedClassOrInterfaceComponentFromResolvedDecl(ResolvedDeclaration resolvedDeclaration,
ParsedComponent parsedComponent) {
if (resolvedDeclaration.isType() && parsedComponent.isParsedClassOrInterfaceComponent()) {
var typeDeclaration = resolvedDeclaration.asType().asReferenceType();
//noinspection OptionalGetWithoutIsPresent
var classOrInterfaceComponent = parsedComponent.asParsedClassOrInterfaceComponent().get();
var fieldList = typeDeclaration.getDeclaredFields();
fieldList.forEach(e ->
classOrInterfaceComponent
.addChild(new ParsedFieldComponent(classOrInterfaceComponent, e)));
var methodList = typeDeclaration.getDeclaredMethods();
var constructorList = typeDeclaration.getConstructors();
constructorList.forEach(e ->
classOrInterfaceComponent
.addChild(new ParsedConstructorComponent(classOrInterfaceComponent, e)));
methodList.forEach(e -> {
classOrInterfaceComponent
.addChild(new ParsedMethodComponent(classOrInterfaceComponent, e));
});
}
}
This where the exception occurs
public ParsedConstructorComponent(ParsedComponent parent, ResolvedDeclaration resolvedDeclaration) {
this.resolvedDeclaration = resolvedDeclaration;
this.parent = parent;
this.printableName = resolvedDeclaration.asMethod().getSignature(); // <--- Exception Occurs here
}
Stack trace
java.lang.UnsupportedOperationException: JavaParserMethodDeclaration{wrappedNode=@Override
public String toString() {
return lineNumber + "|" + type + "|" + isOrphan + "|" + text.replaceAll("\\n", "").trim();
}, typeSolver=com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver@6206b4a7} is not a MethodDeclaration
at com.github.javaparser.resolution.declarations.ResolvedDeclaration.asMethod(ResolvedDeclaration.java:119)
at org.java2uml.java2umlapi.umlComponenets.ParsedMethodComponent.<init>(ParsedMethodComponent.java:27)
at org.java2uml.java2umlapi.umlComponenets.SourceComponent.lambda$generateParsedClassOrInterfaceComponentFromResolvedDecl$3(SourceComponent.java:104)
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
at org.java2uml.java2umlapi.umlComponenets.SourceComponent.generateParsedClassOrInterfaceComponentFromResolvedDecl(SourceComponent.java:103)
at org.java2uml.java2umlapi.umlComponenets.SourceComponent.<init>(SourceComponent.java:34)
at org.java2uml.java2umlapi.umlComponenets.SourceComponentTest.setUp(SourceComponentTest.java:24)
<not relevant after this.>
Please Help Me!
Hi,
I'm trying as a newbie to write some very simple custom java interpreter. I wouldn't want to begin from the start with a wrong approach so I decided to ask for little help here. Here's my question (I hope it's not too basic for you guys):
I wanted to start from the simple stuff and decided to just implement an addition(for integers). I created a visitor for Integer Literals:
public class IntegerLiteralVisitor extends GenericVisitorAdapter<Integer, Void> {
@Override
public Integer visit(IntegerLiteralExpr integerLiteralExpr, Void arg) {
super.visit(integerLiteralExpr, arg);
return Integer.parseInt(integerLiteralExpr.getValue());
}
}
So I guess my next step would be to write a visitor for the BinaryExpression. I want to check if the BinaryExpr.getOperator().equals(BinaryExpr.Operator.PLUS)
and if it is - just add the left and the right side of the BinaryExpression.
How can I technically do that? The left and the right side of a BinaryExpression are from type Expression and i'm having a little trouble putting the whole thing together.
Could someone maybe give me some advice or tell me if I'm approaching this the wrong way?