Here's the deal - I want a way to figure out specifically which methods were touched or changed within the last milestone/iteration so that the methods' Javadoc is checked for correct content, especially for the public API methods.
Any ideas on how to do this, perhaps with an SVN hook?
there is no single command to achieve this, but you can combine some svn commands to achive something similar:
svn diff last tag with your trunk:HEAD revision with --summarize option
svn annotate each file you revceived by step 1 and parse the output to find the changed codelines (their rev is greater than tag-rev.)
mark associated functions or output them into a report file(just remember the last function signature if you parse the file line by line)
the class/methodname is trivial to get for usual java classes, however, if you use innerclasses, it will be more difficult, but then : do they have or need javadoc comments?
An idea, at least: svn diff has the ability to pass arguments to the diff command. One such option is -p, also known as --show-c-function. This would probably figure in a solution of this problem for C code. So, the question becomes: is there a diff implementation that knows enough of the Java syntax to support a similar option? I've Googled, but not found anything yet.
Related
What I'm doing
I'm using reflection in my code to decouple all my classes and To do so I need to be able to dynamically create instances of objects. I've done this by text matching parameter names to input data. To do a text match however, I need access to the formal parameter names rather than the synthetic arg0, arg1 ... that I know gets created if IsNamePresent returns false.
What I've done
I researched how to get the formal names (google searching things like: "when I compile my java classes with the parameter option enabled, does that make reflection work forever? or only one time when the classes are run?" to no useful results). I've also tried searches similar to that here and seen info related to javac with one of the questions being "Drawbacks of javac -parameters flag" as an example. While these addressed parts of my question they really didn't answer the meat of what I need. I've found that in java 8 you can just do "javac -parameters " and you will be fine. Note that I had to use the directory of the jdk as the starting point (my command line input looks exactly like this):
C:\Program Files\Java\jdk-10.0.1\bin>javac -parameters C:\Users\abbotts1\IdeaProjects\project\src\Sales_Rep_Data\*.java
and so far that works without any errors and my project has bytecode compiled files in it now so I know its doing something. Just what exactly (or if its as a result of the above) is a mystery to me because there is no timestamp or anything I can find for these files that points to which command I tried that made it (I've been trying these commands for a while).
Detailed description of question scope
My question is this: is this command line input the only way to get formal parameters. If it is then, am I doing it right (correct input syntax)? If I'm doing it right then how can I make it so that when I debug my code and run param.getName() it actually returns the formal name? So far I've ran the above command on the command line and tried to debug in my java code this line:
Boolean check = param.isNamePresent();
where param is just the parameter coming from a for-each loop that uses the constructor of the class I am getting through reflection. Point is, every-time I run it this Boolean returns false in the debugger and the names are synthetic (arg0, arg1 ect). I want it to return true (and actually use the formal names) so I can debug the rest of my code.
If this isn't the only way to achieve the stated goal of getting formal parameter names then where can I find a better way? I've seen some framework stuff and heard of Eclipse being used to do this, however I don't want to get too deep into new software just to accomplish one thing AND I am working so I don't have administrator privileges (which is why I needed to specify the jdk in cmd directly rather than just set the PATH variables the usual way). This would make it a hassle to have to download something like Eclipse.
Update
I've researched into using annotations to get the parameter names since I have no good idea why the compiled class won't actually store the parameter names. This strategy was suggested in an initial answer (since deleted) and I took it upon myself to go learn some basic annotations. They have worked to a point but right now I'm getting a wrong arguments error where I shouldn't. I've checked the debugger and the number of arguments passed in are the same number needed so it must be a type error with the wrapping/unwrapping according to the javadoc for the newInstance(Object[]) method). I want to be able to initialize null parameters and I think thats the source of my problem (i. e. null type errors or something but not shown as NPE). Other potential sources include the fact that I'm passing in an Object[] and typing it stricter in the class (i.e. newInstance(Object[] array) is creating an instance of a class that has String parameters and other various sub classes of Object including array lists) Since asking about that error here would constitute an XY problem I won't ask but just describe it for clarification on the original question. My original question still stands even as this workaround is being worked on because I'd still love to know why compiling this class with the -parameters flag didn't store the parameter names. I'm 99% sure the class path is correct since I copy pasted it from the directory. This sounds silly but do I have to actually run the class using the below line?
C:\Program Files\Java\jdk-10.0.1\bin>java C:\Users\abbotts1\IdeaProjects\project\src\Sales_Rep_Data\Data_Parser.java
I was under the impression that compiling it with the parameters flag was all you needed and then the formal parameter names would be available.
I am currently taking a project management class and the professor gave this assignment to compare two .java files methods and fields in all cases programmatically. I don't think it's actually possible to do but maybe I am wrong!
The assignment spec is as following (its extremely ambiguous I know)
In this assignment, you are required to write a comparison tool for two
versions of a Java source file.
Your program takes as input two .java files representing those two versions
and reports the following atomic changes:
1. AM: Add a new method
2. DM: Delete a method
3. CM: Change the body of a method (note: you need to handle the case where a method is
relocated within the body of its class)
4. AF: Add a field
5. DF: Delete a field
6. CFI: Change the definition of an instance field initializer (including (i) adding an initialization to a
field, (ii) deleting an initialization of a field, (iii) making changes to the initialized value of a field,
and (iv) making changes to a field modifier, e.g., private to public)
So that's what I am working with and my approach was to use reflection as it allows you to do everything but detect differences in the method body.
I had considered the idea that you could create a parser but that seemed ridiculous, especially for a 3 credit undergrad class in project management. Tools like BeyondCompare don't list what methods or fields changed, just lines that are different so don't meet the requirements.
I turned in this assignment and pretty much the entire class failed it with the reason as "our code would not work for java files with external dependencies that are not given or with java files in different projects" - which is completely correct but also I'm thinking, impossible to do.
I am trying to nail down a concrete answer as to why this is not actually possible to do or learn something new about why this is possible so any insight would be great.
What you got wrong here is that you have started to examine the .class files (using reflection). Some of the information listed above is not even available at that stage (generics, in-lined functions). What you need to do is parsing the .java files as text. That is the only way to actually solve the problem. A very high-level solution could be writing a program that:
reads the files
constructs a specific object for each .java file containing all the informations that needs to be compared (name of the functions, name of the instance variables, etc)
compares the constructed objects (example: addedFunctions = functionsFromA.removeAll(functionsFromB)) to provide the requested results
Note: if this is an assignment, you should not be using solutions provided by anybody else, you need to do it on your own. Likely you will not get a single point if you use a library written by somebody else.
When using Byteman, we have to specify the class and the method in the rule syntax. What if I want to trace program execution using Byteman?
Example: I do not know which methods are being executed when executing a feature of the program. I want to identify the called methods during the feature execution.
Does this mean that I've to add a rule for each method of each class in a given package? Or is there any other way to achieve this?
Yes, essentially you need a rule for every method you want to trace (although there is an easy way to do that -- see below).
Byteman deliberately avoids the use of wildcard patterns for the CLASS and METHOD it is injecting into. That's because using these sort of rules would slow the JVM down enormously.
Why? Well, every time a class is loaded Byteman gets asked "Do you want to transform this class by injecting some code into it?". Currently, Byteman indexes all loaded rules by CLASSNAME. So, answering that question involves a hash table lookup (well, actually, two -- one with the bare name and another with the package qualified name). This means that no answers (which is almost always the right answer) are super-quick. If Byteman were to allow patterns for the CLASSNAME then it could not rely on a simple hash lookup.
If, for example you had a pattern like CLASS org..Foo and 2 classes like org.my.app.FooBar and org.my.app.Bletch how would you decide that the first one matches and the second one does not? You would have to try a pattern match for each pattern rule for every class name. Even a single pattern match is a lot more expensive than a hash table lookup. If you used multiple pattern-based rules then the cost would multiply according to the number of rules.
Ok, so how can you work round this limitation of Byteman? If you want to instrument a lot of classes + methods then I suggest you use a program to generate a rule script containing a rule for each class+method you are interested in. Write a program which reads a file containing entries like
class_name1 method_pattern1
class_name2 method_pattern2
. . .
The file says I want to instrument all methods of CLASS class_name1 whose methods match method_pattern1 and so on.
So long as the target jars are in your classpath you can use the current classloader to load each class by name (call this.getClass().getClassLoader() to get the classloader and then call classloader.loadClass(class_name) to get the desired class). Use reflection to get a list of the class's methods. For each method, if the name of that method matches the corresponding method_pattern output an AT ENTRY rule and/or an AT EXIT rule to your script file.
If you want to see some code whcih does something similar to this look at the contrib/dtest package which is part of the Byteman sources.
https://github.com/bytemanproject/byteman/tree/master/contrib/dtest
If you have any further questions about Byteman the please coem and ask them on the official Byteman user forum provided by the project:
https://developer.jboss.org/en/byteman?view=discussions
regards,
Andrew Dinn
(Byteman Project Lead)
It looks like Byteman is not the right tool for what you want. Better results would be provided by: Understand or JProfiler. Especially in multi-threading environment.
I have a class A<X, Y> and I want to refactor it to A<Y, X> in a way that all the references to it would be modified as well.
I don't think that has been implemented in Eclipse yet. It's a rather rare refactoring, though...
But if your type hierarchy below A is not too complex yet, try using this regex-search-replace (where A|B|C means A and all subtypes of A, e.g. B and C):
\b(A|B|C)<\s*(\w+)\s*,\s*(\w+)\s*>
update: since you want to match more sophisticated stuff, try this (without the artifical line-breaks):
\b(A|B|C)<
\s*((?:\w+|\?)(?:\s+(?:extends|super)\s+(?:\w+|\?))?)\s*,
\s*((?:\w+|\?)(?:\s+(?:extends|super)\s+(?:\w+|\?))?)\s*>
replace by
$1<$3, $2>
Since you're using Eclipse, you can manually check every replacement for correctness
In Eclipse right-click on the method, then Refactor->Change method signature, you can change the order of the parameters there
If you aren't using Eclipse (or another tool that has good refactoring - highly recommended if you're aren't), then I can think of two ways to do this:
First:
If you're using TDD, then write a test that will only succeed when the variables are properly swapped. Then make the change to the method signature, and make sure your test passes.
Second:
1. Remove the 2nd parameter from the method signature, which will throw compilation errors on all calls to that method
2. Go to each of the lines that are failing compilation, and carefully swap the variables
3. Put the 2nd variable back into the method signature, in the new, reversed order
4. Run some tests to make sure it still works the way you expect it to
The second method is obviously ugly. But if you're aren't using an IDE with good refactoring support, compilation errors are a good way to capture 100% of the calls to that method (at least within your project). If you're writing a code library that is used by other people, or by other programs, then it becomes much more complicated to communicate that change to all affected parties.
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.