Refactoring - Collapsible "if" statements should be merged - java

I am trying to clean up our legacy code, and noticed there are many if conditional code that can be merged.
Example -
if (file != null) {
if (file.isFile() || file.isDirectory()) {
/* ... */
}
}
This can be refactored to,
if (file != null && (file.isFile() || file.isDirectory())) {
/* ... */
}
Manually performing this change is a pain. So, I was trying to check on inspection tool and template refactoring in intelliji to help me with this bulk code refactoring.
Could not locate this eclipse IDE too.
Kindly suggest, is there an option in Intelliji/Eclipse for this

In IntelliJ IDEA put the text cursor on the first if keyword, press Alt+Enter and invoke Merge nested 'if's.
You can also use Structural Search & Replace to perform this operation in bulk. Use the following search pattern:
if ($a$) {
if ($b$) {
$statement$;
} else $void$;
} else $void$;
Click Edit Variables... and set the minimum and maximum count of statement to 0,∞. Also set the minimum and maximum count of void to 0,0
Use the following replacement pattern:
if (($a$) && ($b$)) {
$statement$;
}
Note that this replacement will introduce redundant parentheses in some cases to prevent changes the semantics of the code. These can later be removed again by invoking Run Inspection by Name and running the Unnecessary parentheses inspection.

The AutoRefactor Eclipse plug-in can do this for you in batch.
See http://autorefactor.org/html/samples.html and select CollapseIfStatementSample.java. You can do this on a whole file, package, or even project.
There is a refactoring to remove unnecessary parentheses too: SimplifyExpressionSample.java (see e. g. line 144).

Related

How to change Eclipse extraced method template?

The code standard at my work, is to put the "{" on their own line instead of after the arguments of a method. We're using lots of method extraction as we are in a refactoring heavy state.
Unfortunately, auto-extracted methods place the "{" on the wrong line and since no dev notices it every time, our standard isn't so standard anymore. Is there a way to change it? Thanks
I want this
void foo () {
//stuff
}
to be this
void foo ()
{
//stuff
}
In Window > Preferences > Java > Code Style > Formatter, edit your active profile.
Method declaration in the Braces tab allows you to define this behaviour.

How to get rid of the class/method is never used android studio

I am running a code were it detects the highest sound made in the room. I have written my code (with some help), but warnings keep popping up saying that the class and methods aren't used. Please help.
public class SoundMeter {
private MediaRecorder soundCapture = null;
public void start() throws IOException {
if (soundCapture == null) {
soundCapture = new MediaRecorder();
soundCapture.setAudioSource(MediaRecorder.AudioSource.MIC);
soundCapture.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
soundCapture.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
soundCapture.setOutputFile("/dev/null");
soundCapture.prepare();
soundCapture.start();
}
}
public void stop() {
if (soundCapture != null) {
soundCapture.stop();
soundCapture.release();
soundCapture = null;
}
}
public double getAmplitude() {
if (soundCapture != null){
return soundCapture.getMaxAmplitude();
}
else{
return 0;
}
}
}
If there are methods that aren't used, and you have no plan to use them, you should just delete them. They take up space in the APK and space is valuable when you only have 100MB before you have to use expansion files.
Some tools like Proguard can optimize away unused methods, but again, if there's no use for it, get rid of it.
If there are unused methods and classes you are planning to use, do not delete them.
Android Studio shows suggestions if you click Alt+Enter, including removal, which you can apply to the entire file if you don't want to remove them manually.
And if you plan on using them, you can get rid of the warning by suppressing it - again Alt+Enter, but click the arrow left, and it'll auto-generate a suppression annotation for whatever scope you want, or my manually adding:
#SuppressWarnings("unused")
To the scope you want to suppress it in (as in either the class, or only the function).
But remember: it's a warning, not an error. You can ignore it, as it doesn't have any consequences aside a potentially bloated APK/Jar

Force YAML Tag on JavaBean properties

I have been using SnakeYAML for certain serialization/deserialization. My application combines Python and Java, so I need some "reasonable behaviour" on the Tags and the Types.
My problem / actual status on the YAML document:
!!mypackage.MyClassA
someFirstField: normal string
someSecondField:
a: !!mypackage.ThisIsIt
subField: 1
subOtherField: 2
b: !!mypackage.ThisIsIt
subField: 3
subOtherField: 4
someThirdField:
subField: 5
subOtherField: 6
I achieved the use of the tags inside collections (see example someSecondField) by reimplementing checkGlobalTag and simply performing return. This, if I understood correctly, ensures no smart cleanness of snakeyaml and maintains the tags. So far so good: I need the type everywhere.
However, this is not enough, because someThirdField is also a !!mypackage.ThisIsIt but it has implicit tag and this is a problem (Python does not understand it). There are some other corner cases which are not to the point (tried to take some shortcuts in the Python side, and they became a Bad Idea).
Which is the correct way to ensure that the tags appear for all user-defined classes? I assume that I should override some methods on the Representer, but I have not been able to find which one.
The line responsible for that "smart tag auto-clean" is the following:
if (property.getType() == propertyValue.getClass())
Which can be found in representJavaBeanProperty, for the class Representer.
The (ugly) solution I found is to extend the Representer and #Override the representJavaBeanProperty with the following:
protected NodeTuple representJavaBeanProperty(Object javaBean,
Property property,
Object propertyValue,
Tag customTag) {
// Copy paste starts here...
ScalarNode nodeKey = (ScalarNode) representData(property.getName());
// the first occurrence of the node must keep the tag
boolean hasAlias = this.representedObjects.containsKey(propertyValue);
Node nodeValue = representData(propertyValue);
if (propertyValue != null && !hasAlias) {
NodeId nodeId = nodeValue.getNodeId();
if (customTag == null) {
if (nodeId == NodeId.scalar) {
if (propertyValue instanceof Enum<?>) {
nodeValue.setTag(Tag.STR);
}
}
// Copy-paste ends here !!!
// Ignore the else block --always maintain the tag.
}
}
return new NodeTuple(nodeKey, nodeValue);
This also forces the explicit-tag-on-lists behaviour (previously enforced through the override of the checkGlobalTag method, now already implemented in the representJavaBeanProperty code).

Eclipse code formatter: Perform a single action

How can I perform a single action in Eclipse Java code formatter? For example I want to clean up every occurrence of
if (bla) {
...
}
else {
...
}
To this
if (bla) {
...
} else {
...
}
But nothing else. I need this to clean up specific findbugs issues. If I'd run the whole code formatter actions on the project, it would lead us into merge hell. So I want to handle such findbugs issues one by one and therefore It would be great to just execute such a single rule. The Version of Eclipse wouldn't matter, right now I tried with the latest Luna.
A quick way to do this would be to use the search and replace option in eclipse. Go to Search menu->File
Search for : \}\s+\n\s+else\s+\{
Replace with : } else {

How to detect that code is running inside eclipse IDE

How to detect that code is running inside eclipse IDE
I am not aware of a generic way to get this kind of information.
One suggestion:
When you start a Java program (or a web server) inside Tomcat, simply add an argument that will indicate that this program is launched by Eclipse.
You can do that by opening the "Open Run Dialog" ("Run" menu), then select your type of application and add in the "Arguments" tab a -DrunInEclipse=true.
In your Java code, you can check the value of the property:
String inEclipseStr = System.getProperty("runInEclipse");
boolean inEclipse = "true".equalsIgnoreCase(inEclipseStr);
This way, if the program is not running inside Eclipse (or unfortunately if you forgot to set the property) the property will be null and then the boolean inEclipse will be equal to false.
Although I agree that having the code detecting a single IDE as the dev env is not an optimal solution, the following code works.
Like others proposed, using a flag at runtime is better.
public static boolean isEclipse() {
boolean isEclipse = System.getProperty("java.class.path").toLowerCase().contains("eclipse");
return isEclipse;
}
1) Create a helper method like:
public boolean isDevelopmentEnvironment() {
boolean isEclipse = true;
if (System.getenv("eclipse42") == null) {
isEclipse = false;
}
return isEclipse;
}
2) Add an environment variable to your launch configuration:
3) Usage example:
if (isDevelopmentEnvironment()) {
// Do bla_yada_bla because the IDE launched this app
}
Actually the code is not being run inside Eclipse, but in a separate Java process started by Eclipse, and there is per default nothing being done by Eclipse to make it any different than any other invocation of your program.
Is the thing you want to know, if your program is being run under a debugger? If so, you cannot say for certain. You CAN, however, inspect the arguments used to invoke your program and see if there is anything in there you do not like.
If your workspace matches some pattern like "/home/user/workspace/Project" you can use the code below:
Boolean desenv = null;
boolean isDevelopment() {
if (desenv != null) return desenv;
try {
desenv = new File(".").getCanonicalPath().contains("workspace");
}
catch (IOException e) {
e.printStackTrace();
}
return desenv;
}
A more generic and precise way, that can be used on any IDE would be loop at:
ManagementFactory.getRuntimeMXBean().getInputArguments()
looking for "-Xdebug" || (starting with) "-agentlib:jdwp=".
I came with this from #saugata comment here.
This is excellent if you want to throw a conditional exception preventing the application from simply exiting. Use a boolean like "ideWait" and add it to Eclipse watch expressions as ideWait=false, so whenever you stop at that throw, and "drop to frame" you can continue debugging happily (I mean it!)
I don't think there is any way to do this. But what I would suggest is just a command line argument such as 'debug'. Then in your main method just do
if (args.length > 0 && args[0].equalsIgnoreCase("debug")) {
// do whatever extra work you require here or set a flag for the rest of the code
}
This way you can also get your extra code to run whenever you want just by specifiying the debug parameter but under normal conditions it will never execute.
This might work if your alternative execution work flow provides a different set of dependencies:
boolean isRunningInEclipe = false;
try {
Workbench.getInstance();
isRunningInEclipe = true;
} catch (NoClassDefFoundError error) {
//not running in Eclipse that would provide the Workbench class
}
You could detect if you're inside a JAR or not, as per Can you tell on runtime if you're running java from within a jar?
Eclipse will run your app from the classes/ dir, whereas most of your end users will be running the app from a JAR.
System.out.println("Is my parent eclipse[.exe]? " +
ProcessHandle.current()
.parent()
.flatMap(parent -> parent.info().command())
.orElse("")
.matches("^.*eclipse(\\.exe)?$"));
You may try something like this:
if (ClassLoader.getSystemResource("org/eclipse/jdt/core/BindingKey.class")!=null){
System.out.println("Running within Eclipse!!!");
} else {
System.out.println("Running outside Eclipse!!!");
}

Categories