I'm trying to write a Java plugin that does a custom refactoring that involves inserting new assignment statements, and I'm not sure how to create a PsiAssignmentExpression.
I have a PsiElementFactory, but while I see PsiElementFactory#createIdentifier and PsiElementFactory#createVariableDeclarationStatement, I don't see how to do an assignment.
I tried looking for the extract variable refactoring in the base source code to try and find an example but wasn't able to find it yet.
P.S. I looked at IntelliJ IDEA plugin development: how to modify the Psi tree?, which recommended creating PsiElements by creating a PsiFile and then extracting the element from it back in, but I am wondering if that's specific to creating a custom language that doesn't have the Java api.
Use PsiElementFactory#createExpressionFromText and pass in the text of the assignment you want to create. For example "s = \"Hello World\"".
Related
First of all this might be a dumb question and I searched for some days but didn't find an answer. So if there is an existing answer concerning my question, I would be grateful for a link.
I don't know if anyone of you ever coded Spigot, Paper or Bukkit, but there was a class called YamlConfiguration which had the following methods:
public FileConfiguration cfg = YamlConfiguration.loadConfiguration(file);
cfg.set(path.path2, "hello");
cfg.getInt/String/...(path.path2); (which obviously returns "hello")
cfg.save(file);
The produced file then looks like this:
path:
path2: "hello"
So you could basically save any value in those files and reuse them even if your program has been restarted.
I know have moved forward from Spigot/Paper to native Java and I'm missing something like that Yaml-thing. The only thing I found was a kind of a config file, where every time the whole file is overwritten, when I try to add values.
Can you show me a proper way of saving values to a file? (would be nice without libraries)
I'm missing sth like that Yaml-thing
SnakeYAML should have you covered. Without knowing anything about your use-case, it makes no sense to discuss its usage here since its documentation already does cover the general topics.
The only thing I found was a kind of a config file, where everytime the whole file is overwritten, when I try to add values.
Saving as YAML will always overwrite the complete file as well. Serialization does not really work with append-only. (Serialization is the term to search for when you want functionality like this, by the way.)
If you mean that previous values were deleted, that probably was because you didn't load the file's content before or some other coding error, but since you don't show your code, we can only speculate.
Can you show me a proper way of saving values to a file?
People will have quite different opinions on what would be a proper way and therefore it is not a good question to ask here. It also heavily depends on your use-case.
would be nice without libraries
So you're basically saying „previously I used a library which had a nice feature but I want to have that feature without using a library“. This stance won't get you far in today's increasingly modular software world.
For example, JAXB which offers (de)serialization from/to XML was previously part of Java SE, but has been removed as of Java SE 11 and is a separate library now.
I've been using this instruction to get the name of a method which is currently being used.
currentThread().getStackTrace()[1].getMethodName()
It works fine when I developed Spring Framework or other simple programmings.
However, It seems it works differently in Android Studio. I get time instead of the name of a method.
The reason why I try to use this instruction is for debugging. I used to use
Log.d(TAG, "Method()");
However, The problem when I use this... I should type its method name each. So, To implement this instruction in all the different methods with the same instruction. I found out using currentTrace(). But when I use this on Android Studio. I just get 'geStackTrace' instead of the current method name.
Is there any way to implement it correctly or better way for debugging?
Try this
StackTraceElement[] stacktraceObj = Thread.currentThread().getStackTrace();
stacktraceObj[1].getMethodName();
For further reference, checkout the links
https://www.badprog.com/android-api-getting-the-current-method-name-with-stacktraceelement
https://developer.android.com/reference/java/lang/Throwable.html#getStackTrace()
If typing it out every-time is the issue use the default live templates for log statements.
Use cmd+j(ctrl + j in windows) and look for logd, logi, logw or loge.
By default it prints the method and a colon. You can customize it in preferences.
There's logt for creating a TAG too.
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.
I have a multilingual web application that gets all of the translations from a single object, for example lang.getTranslation("Login") and the object is responsible for finding the translation in an xml file in the user's language.
What I'd like to do is a script / custom static analysis that outputs all the missing translations and translations that are no more used in the application. I believe I should start by programmatically finding every call to the getTranslation method and the string parameter, storing the data in a special structure and comparing it to all the translation files.
Is there a library that will allow me to do this easily? I already found Javassist but I can't use it to read the parameter values. I also tried grepping, but I'm not sure if that's a robust solution (in case there will be a call to another class that has a getTranslation method). I know Qt has a similar mechanism for finding translatable strings in the code, but that's a totally different technology..
I'm asking this because I'm quite sure there's a good existing solution for this and I don't want to reinvent the wheel.
Ok, here's how I did it. Not the optimal solution, but works for me. I created a utility program in Java to find all the method calls and compare the parameters to existing translations.
Find all classes in my project's root package using the Reflections library
Find all getTranslation method calls of the correct class in the classes using the Javassist library and create a list of them (contains: package, class, row number)
Read the appropriate .java files in the project directory from the given row until the ';' character
Extract the parameter value and add it to a list
Find the missing translations and output them
Find the redundant translations and output them
It took me a while to do this, but at least I now have a reusable utility to keep the translation files up to date.
I'm just starting to learn and the books say that I can use "pre-coded" classes and objects. How do I call these classes/objects in the beginning of my program? I understand basically what they are, and the idea that I can use these classes/objects in place of writing fresh code every time, but I cannot seem to figure out where I find these things and how I implement them.
You certainly talk about the Java classes that come in JRE/JDK.
Those are used by including the jar in your classpath and provides the "default" java classes.
Like String in java.util package.
If you want to look at them, in the JDK you'll find the sources of these class.
"Pre-coded", or pre-written Java classes, are pretty much the same concept as the Java API - someone has written the code for you, was kind enough to document how you can use the code, and you may create instances (as necessary) through the prescribed way.
Say, for instance, I want an ArrayList holding Strings. I would then code ArrayList<String> words = new ArrayList<String>(). You wouldn't have to go through the process of writing a dynamic self-expanding vector.