While developing Eclispe plugin, I am able to programmatically rename a class-field using the following code.
RenameSupport renameSupport = RenameSupport.create(field, newName, RenameSupport.UPDATE_REFERENCES);
renameSupport.perform(workbench.getShell(), workbench);
But it applies the changes to the actual source files. Is there anyway that can be prevented? I just need the renamed code internally (for performing some other computations), must not change the actual source.
Please suggest.
You could copy it into a temporary file with File.createTempFile() and then rename the code in your temporary file, if RenameSupport lets you do that. If it doesn't, then you can copy the original to a temporary file and copy it back once your other computations are finished.
First, create an instance of RefactoringDescriptor. Then, invoke createRefactoring on it to create an instance of Refactoring. You can get the change object by invoking createChange on the Refactoring object. The Change object will tell you how the refactoring is going to change the code. Finally, you can invoke the method perform on the Change object to apply it on the underlying files.
The plugin org.eclipse.jdt.ui.tests.refactoring contains automated unit tests for Java refactorings in Eclipse. For a concrete example of how to invoke a refactoring programmatically, refer to org.eclipse.jdt.ui.tests.refactoring.RefactoringTest.
Related
I'm making a testing tool. For this, I need to access a class which is present in Test folder within same project.
I've a class mutant.java in src folder. And I've another class TestAll.java which is present in Test folder within same project. I need to access TestAll.java class in mutant.java class. But I can't be able to find a way to do that.
public void runTest()
{
TestAll a=new TestAll();
}
When I create an object of TestAll.java class in mutant.java class, It gives me an error and didn't recognize that class. I want to access TestAll.java class but don't know How can I?
I need to access TestAll.java class in mutant.java class
No, you need to understand how to properly organize the dependencies within a project.
Your "production" code, that stuff that sits in src is never ever supposed to use something from the test folder. End of story.
Reasoning: src represents the content that you "ship" to your customer. That is your product. Your own test code is not your product. In order to prevent you from (accidentally) releasing "test stuff" to your customer, you ensure that src can't use test. That is why any IDE or build tool organizes your project based on that simple rule.
Thus, the real answer is: you should step back, and rethink what you intend to do. The purpose of any test is to prepare some sort of setup, to then run some production code, and verify the expected behavior.
If your current design prevents that, then, as said: stop right there. Ideally, look out for some peer/tutor to sit down with you and rethink your design, and change it accordingly.
Every second you invest into "how do I use stuff from test within src" is a waste of your energy.
I'm working on an Eclipse plugin that enables traceability. I am implementing a notification system that tells the user whenever a traced item changes (is removed, renamed or edited) and for that purpose I implemented an IResourceChangeListener, but that doesn't give me all the support that I want for Java elements.
For example, when I rename a Java method inside a .java file, it only tells me which file has been edited, but I would like to have the info about the method as well. I know that this can be achieved with implementing the IElementChangedListener, but is there any way around it? Do I really have to implement two listeners (ResourceListener for other files and ElementChangedListener just for java elements) or can I somehow get the IJavaElementDelta (normally obtained from the ElementChangedListener) from the IResourceDelta? Thanks!
These two deltas are completely unrelated. You need to use both listeners.
Try to check this link example 5. There is some method with this description:
Converts an IResourceDelta and its children into
the corresponding IJavaElementDeltas.
Return whether the delta corresponds to a resource on the classpath.
If it is not a resource on the classpath, it will be added as a non-java
resource by the sender of this method.
So I suppose it could be possible.
The links leads here which should you check ass well. Method public void processJavaDelta(IJavaElementDelta delta)
I have a class which behavior I would like to change. I need to replace private method with another realization. Common reflection techniques allow to modify private variable or to invoke private methods. But I find little information about replacing entire methods.
I presume that there are advanced techniques to do so. May be its impossible with standard java reflection but there are probably other tools to recompile byte code in runtime.
Modify & replace:
One option is to mask the class with a modified copy (modify code, recompile code, add modified classes to the classpath before patched classes), similar to the approach used here to inspect how a normally unavailable method works.
If you do not have sources to modify, you can "reverse" almost any .class file into more-or-less readable source code using decompilers. Notice that, depending on licensing, you may not have permission to do so and/or to redistribute your changes.
Patch via agent:
You can also patch the methods using the -javaagent:<jarpath>[=<options>] commant-line option. The "agent" is a jar that gets to modify loaded classes and alter their behaviour. More information here.
Mock:
If you have control over where the methods are called, you can replace the target instance with a stubbed version. Libraries such as Mockito make this very, very easy:
LinkedList mockedList = mock(LinkedList.class);
// stubbing appears before the actual execution
when(mockedList.get(0)).thenReturn("first");
Even though Mockito does not support mocking private methods natively (mostly because it is considered bad manners to look at other classes' privates), using PowerMock allows you to do so (thanks, #talex).
You can't replace method in runtime (at least without hack into JVM). But you can replace whole class. There are several way to do it. For example you can use thing called "aspect".
But from my experience I can say that if you need to do this you have wrong turn somewhere in beginning of you way.
Maybe you better make one step back and look at whole picture
Instead of going for advanced techniques, there is a simple trick to achieve this.
If you class is part of an open-source jar, get source code of this class file from grepcode.com. Change the method that you want to change and compile it. And update your jar file/classpath with this updated class file.
With reference to the following link, I have created the classes at run time, http://blog.javaforge.net/post/31913732423/howto-create-java-pojo-at-runtime-with-javassist. Now I need to view the created class that means Where will it create the class file? Is it possible to save it on disk/work space?
You can call cc.writeFile() right before or right after you call cc.toClass() to store a class file containing the bytecode of the generated class.
I don’t know of an equivalent operation to get a source file, however, you may consider the fact that you are actually generating the source code already (at least for the methods) and passing it to Javassist’s CtClass in order to be compiled.
So it’s not that hard to use the same code to generate the source code for an entire class as you only need to concatenate these methods, add field declarations and enframe it with a class body. After all, generating a source file means just writing a text file in a format that you already know very well…
The process of taking a java object and writing it to a text-like file is called serialization. The language has good built in support for this.
Oracle's documentation for these features can be found here and a tutorial here.
In general it's pretty easy to use and well understood and provides some clever features including the ability to detect if one version of a program saved the record but an incompatible version is trying to load it.
Also this stack overflow question will be useful to you.
Why would you want do do that? It's possible to create files from Pojos, then youll have to follow this tutorial:
http://www.mkyong.com/java/how-to-write-an-object-to-file-in-java/. But then you'll only write the contents of the fields to a file.
My need is pretty simple: I want to change a method call objClass1.method1() by a call objClass2.method2() in my whole Eclipse project. Unfortunately, I can't find a plugin able to do this. Can you help?
Edit:
To be more accurate, objClass1 is part of a third party library, so I need to change the method calls. I can't start at the method definition. When I right-click on a method1 call, I have no "rename" option in my "Refactor" menu.
I don't want to change or rename my methods. I want to exchange one call by another in my whole project.
An example of what needs to be done:
Before refactoring:
Injector injector=Guice.createInjector(new IContactModule());
After refactoring:
Injector injector=IContactInjectorSingleton.getInjector();
And this needs to be done a several points in my project.
What you ask for is no refactoring. A refactoring is defined as "a change that alters the code while not changing the behavior of the code". In this sense renaming a class or renaming a method is a refactoring (you change the code but the program does the same as before). But what you suggest does NOT preserve the behavior of the code so there will never be a "refactoring" for this.
Of course one might be able to write a plugin that is able to perform the text changes you want in a more or less safe way. But this will only work in very specific circumstances (what if your new method needs an argument the old one dons't need? What if there are more than one method with the same name but different parameters? ...). So I don't believe such a plugin exists, nor it makes much sense to develop such a plugin.
Just right click on the class/method name and choose Refactor > Rename.
EDIT:
To be more accurate, objClass1 is part of a third party library, so I need to change the method calls. I can't start at the method definition. When I right-click on a method1 call, I have no "rename" option in my "Refactor" menu.
Hence I would suggest you to simply make a replacement:
Search menu > File, type the old name, choose the context of the search ("Enclosing project"), click on Replace and type the new name.
EDIT2:
From the example you added to the question I think that a manual replacement, using the tool I just suggested, it's the best way. It's a complex issue, as #Arne pointed out, so it's better to make it in a controlled way. Moreover I doubt it is such a frequent operation to require a plugin to be built.
You could use the eclipse refactoring by selecting the methods name. Right click for context menu or Alt-Shift-R, in the Rename-Dialog a preview dialog is available which shows all suggested changes in one place.
First, move the body of objClass1.method1() into objClass2.method2(), and have method1 simply call method2. It may not be quite as "simple" as that, if for instance method1 uses fields of Class1 for instance, in which case you should probably include this as a parameter to the new method and perhaps use getters for the fields. If you can make the method static before doing this, it will be easier to avoid those kinds of problems. Anyway, make that transformation, so method1 is just calling method2. Now use the Inline Method refactoring to make method1 go away. You're done.