i would like to analyse my code, classes and methods : my goal is to create a sequence diagram by reversing my code
But , i would like to analyse it without running the application
So, i already get my classes and methods names
What i am looking for now , is to read/get the content of a method , without using a regex expression to parse my entire file
Is there a simple way to get it ?
Thanks
I think you can use Groovy's Global AST Transforms to analyze your code. It will give you access to the abstract syntax tree. From there you can walk in the tree nodes of your code. This is 'hooking' in the Groovy compilation process.
I'm not sure it will work with Java code. Java is Groovy code, so in theory it could work, but the compiler won't go through .java files.
Related
I am trying to compare CFGs using AST comparison. I have tried the Eclipse AST Parser, it's great. But I'm using IntelliJ IDE so can't use it. I explored the Java parser but it returns compilation unit and work on complete Java files. Please suggest a way or APIs to get the Abstract Syntax Trees of basic blocks (few lines of code), further in I should be able to compare generated ASTs.
I've never done this but what about taking the text of the basic block and putting a trivial wrapper around it:
class AST {
void method() {
// basic block here
}
}
And passing that to the parser? It would give you more than you wanted, but you could navigate a couple of nodes down in the AST and the entire subtree below that would be the AST you wanted.
ANTRLR newbie question. Say for a given grammar ANTLR maven plugin has created all the necessary Java classes to traverse and parse a text. And it works just fine when used as prescribed in "The Definitive ANTLR4 Reference".
Now imagine I need to reuse the generated classes to parse an expression which is defined by a rule buried somewhere deep in the grammar file.
However the Reference doesn't seem to provide a clue as to how to select a specific rule as a starting one, the generated classes always expect the whole grammar tree being present in the source.
Using the generated classes as-is doesn't work either, cause the corresponding listener and parser methods expect a context parameter which can only be created when having a "parent context" and an "invoking state" which I don't know how to define.
The only (and rubbish) solution I came up with so far, is splitting the grammar into two files so that the low-level rule in question would become top-level one, and import the latter into the first.
Do I miss something obvious here? Any help would be appreciated.
This is very simple. Load your input stream with the text that you wanna match against one of the subrules, then call the function for that subrule in the parser as you did with the main rule. Each grammar rule is represented by a function, which you can simply call for your subtext and it will generate a stripped down parse tree then, which applies only to this subrule (and it's children).
I want to get typed AST from JavaParser or another parser of Java code. It means I would be able to get the type for a specific variable or parameters+returning type of a method. I googled a lot about this feature of JavaParser, but didn't find anything, I assume this is because JavaParser makes untyped AST. So, advise me how I can get this. But please don't say to parse all the code and make my own set of types, I tried and this is very hard, I think this is harder than making my own AST parser.
I am a JavaParser contributor and I just did that in Clojure, on top of JavaParser. I explain how implement that in one post How to build a symbol solver for Java, in Clojure
JavaParser, or any other parser just build an Abstract Syntax Tree (AST) of the code, then you have to resolve symbols to understand which references are associated to which declarations.
Suppose you have in your code something like:
a = 1;
Now, to understand the type of a you should find where it is declared. It could be a reference to a parameter, to a local variable, to field declared in a current class or to a field inherited. If it is a field inherited you should find the code (or the bytecode) of the parent class and look there for the declaration of a. A parser does not do that, a parse just take a string (or a file) and build an AST.
Build a symbol resolver is not rocket science but it requires a bit of work. The solution I described in the post linked above is available on GitHub and I would be glad to help you use it if you want (even if it is written in Clojure you can call it from Java quite easily)
I have an app that gets the content of an html file.
Lets say the text of the page is:
String[] arr = new String[] {"!","#","#"};
for (String str : arr) {
write(str);
}
Can I somehow compile this text and run the code within my app?
Thanks
Use Janino. It's a java runtime in-memory compiler. Way easier than BCEL and the likes.
From the homepage:
"What is Janino?
Janino is a super-small, super-fast Java™ compiler. Not only can it compile a set of source files to a set of class files like the JAVAC tool, but also can it compile a Java™ expression, block, class body or source file in memory, load the bytecode and execute it directly in the same JVM. Janino is not intended to be a development tool, but an embedded compiler for run-time compilation purposes...
You can use the javac compiler, or the Java Compiler API or the BeanShell library (or similar). You can compile it any number of ways, none terribly simple which often leads to finding another way to solve your problem.
Instead of generating source and compiling its common to generate byte code directly using ASM, Javaassist, BCEL or the like
This appears to be the same as
for(char ch: "!##".toCharArray())
write(ch);
which is likely to be the same as
write("!##");
Since the question is tagged android:
The answers posted so far only apply to the “standard” JVM, not to Android's Dalvik VM. In principle, it is possible on Android too. I don't know if there's an existing Java compiler that you can embed, but you would probably generate the final Dalvik bytecode using dexmaker. It may be possible to combine an existing Java compiler with dexmaker.
But please think twice before attempting anything like this, and be very careful. The last thing you want is a way for an attacker to execute arbitrary code on your user's hardware.
You can try javassist, it's not full Java though.
This is not usually that hard to do, but I have to ask can you give more detail on exactly what it is you are trying to accomplish. I do this type thing all the time. This is just another example of getting information from the user and using it somewhere else in your code. Since your using java maybe look at the string API http://docs.oracle.com/javase/6/docs/api/java/lang/String.html and the string tokenizer http://docs.oracle.com/javase/6/docs/api/index.html?java/lang/package-summary.html
Now you can break the string down into single values one word or other value at a time. From there you can use functions such as isNAN() from the float or double class to determine if it a number or string or whatever it is your testing for. Now you know what you’re dealing with you can reconstructed the data in a usable form.
Note for values if you want to use them as values use Float(string value) constructor. i.e Float x = new Float(myString)
Is there any way to override the line numbers in Java (e.g., by using some kind of preprocessor directive)?
I am "compiling" a high-level language, down to Java byte code using Janino. I need compiler errors to report the line from the original file, not the generated Java code.
C# has the #line directive, and I've successfully exploited it to map line numbers from a source file to the compiled result. I need the same for Java.
Thanks!
I've never seen it used for other than JSP, but JSR-45 was designed to be used for this purpose for any source language. The process involves creating a second file in a special format ("SMAP") that maps line numbers in the original source to line numbers in the generated Java source code.
Unfortunately, no, there isn't an equivalent #line directive in Java. The best you can do is modify the source after it's been generated by deleting/inserting newlines to match the real source (or modify the code generator). Or, you could modify the line numbers stored in the binary class files after they've been compiled, but that will likely be even more painful.
Using Janino you can derive from Scanner and override the location() method. This method returns a Location object. You can override the read() method to look for annotations, within comments for instance (added during code generation), that hold line number information.
You simply pass your scanner to the SimpleCompiler.cook() method and you can control what filename, line and column get reported on error.
Instead of generating Java code as your intermediate language, you could try using JVM assembler. Jasmin has nice syntax, and you are free to insert .line directives at appropriate places in your code. You can also can also specify the original source file using the the .source directive.
Granted, going the assembler route may be more hassle than it's worth :)
There is no simple solution. One workaround would be to generate a line number map from [your language] to Java when you generate the code. You can pipe the compiler output and use the map to replace Java's line numbers with your line numbers.