├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── inspectionDescriptions ├── InlineNestedElse.html ├── InverseElseComparator.html └── PointlessBitwiseComparator.html ├── main ├── kotlin │ └── world │ │ └── gregs │ │ └── intellij │ │ └── plugins │ │ ├── DeobfuscateToolBundle.kt │ │ ├── DeobfuscateUtil.kt │ │ ├── bitwise │ │ └── PointlessBitwiseComparatorInspection.kt │ │ └── flow │ │ ├── InlineNestedElseInspection.kt │ │ └── InverseElseComparatorInspection.kt └── resources │ ├── META-INF │ └── plugin.xml │ └── world │ └── gregs │ └── intellij │ └── plugins │ └── DeobfuscateToolBundle.properties └── test ├── kotlin └── world │ └── gregs │ └── intellij │ └── plugins │ ├── LightInspectionTester.kt │ ├── LightQuickFixTester.kt │ ├── LightTester.kt │ ├── bitwise │ ├── PointlessBitwiseComparatorFixTest.kt │ └── PointlessBitwiseComparatorInspectionTest.kt │ └── flow │ ├── InlineNestedElseFixTest.kt │ ├── InlineNestedElseInspectionTest.kt │ ├── InverseElseComparatorFixTest.kt │ └── InverseElseComparatorInspectionTest.kt └── resources ├── fixes └── world │ └── gregs │ └── intellij │ └── plugins │ ├── bitwise │ └── pointless_bitwise_comparator │ │ ├── RemoveBitwiseAndComparator.after.java │ │ ├── RemoveBitwiseAndComparator.java │ │ ├── RemoveBitwiseComparator.after.java │ │ ├── RemoveBitwiseComparator.java │ │ ├── RemoveComplimentAndComparator.after.java │ │ ├── RemoveComplimentAndComparator.java │ │ ├── RemoveComplimentComparator.after.java │ │ ├── RemoveComplimentComparator.java │ │ ├── RemoveFlippedBitwiseComparator.after.java │ │ └── RemoveFlippedBitwiseComparator.java │ └── flow │ ├── inline_nested_else │ ├── InlineNestedElse.after.java │ ├── InlineNestedElse.java │ ├── InlineNestedElseBoolean.after.java │ ├── InlineNestedElseBoolean.java │ ├── InlineNestedElseMethod.after.java │ └── InlineNestedElseMethod.java │ └── inverse_else_comparator │ ├── InvertDoubleElseComparator.after.java │ ├── InvertDoubleElseComparator.java │ ├── InvertMethodElseComparator.after.java │ ├── InvertMethodElseComparator.java │ ├── InvertRangeElseComparator.after.java │ ├── InvertRangeElseComparator.java │ ├── InvertSingleElseComparator.after.java │ └── InvertSingleElseComparator.java └── test └── world └── gregs └── intellij └── plugins ├── bitwise └── pointless_bitwise_comparator │ ├── EqualsBitwiseComparator.java │ ├── GreaterThanBitwiseComparator.java │ ├── GreaterThanEqualBitwiseComparator.java │ ├── IgnoredComparators.java │ ├── LessThanBitwiseComparator.java │ ├── LessThanEqualBitwiseComparator.java │ ├── NotEqualsBitwiseComparator.java │ ├── PointlessBitwiseComparator.java │ └── TildeComparator.java └── flow ├── inline_nested_else └── NestedElse.java └── inverse_else_comparator ├── InverseBooleanComparator.java ├── InverseElseComparator.java ├── InverseMethodComparator.java └── InverseRangeComparator.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/kotlin,gradle,intellij 2 | # Edit at https://www.gitignore.io/?templates=kotlin,gradle,intellij 3 | 4 | ### Intellij ### 5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 6 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 7 | 8 | # User-specific stuff 9 | .idea/**/workspace.xml 10 | .idea/**/tasks.xml 11 | .idea/**/usage.statistics.xml 12 | .idea/**/dictionaries 13 | .idea/**/shelf 14 | 15 | # Generated files 16 | .idea/**/contentModel.xml 17 | 18 | # Sensitive or high-churn files 19 | .idea/**/dataSources/ 20 | .idea/**/dataSources.ids 21 | .idea/**/dataSources.local.xml 22 | .idea/**/sqlDataSources.xml 23 | .idea/**/dynamic.xml 24 | .idea/**/uiDesigner.xml 25 | .idea/**/dbnavigator.xml 26 | 27 | # Gradle 28 | .idea/**/gradle.xml 29 | .idea/**/libraries 30 | 31 | # Gradle and Maven with auto-import 32 | # When using Gradle or Maven with auto-import, you should exclude module files, 33 | # since they will be recreated, and may cause churn. Uncomment if using 34 | # auto-import. 35 | # .idea/modules.xml 36 | # .idea/*.iml 37 | # .idea/modules 38 | 39 | # CMake 40 | cmake-build-*/ 41 | 42 | # Mongo Explorer plugin 43 | .idea/**/mongoSettings.xml 44 | 45 | # File-based project format 46 | *.iws 47 | 48 | # IntelliJ 49 | /out/ 50 | 51 | # mpeltonen/sbt-idea plugin 52 | .idea_modules/ 53 | 54 | # JIRA plugin 55 | atlassian-ide-plugin.xml 56 | 57 | # Cursive Clojure plugin 58 | .idea/replstate.xml 59 | 60 | # Crashlytics plugin (for Android Studio and IntelliJ) 61 | com_crashlytics_export_strings.xml 62 | crashlytics.properties 63 | crashlytics-build.properties 64 | fabric.properties 65 | 66 | # Editor-based Rest Client 67 | .idea/httpRequests 68 | 69 | # Android studio 3.1+ serialized cache file 70 | .idea/caches/build_file_checksums.ser 71 | 72 | ### Intellij Patch ### 73 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 74 | 75 | # *.iml 76 | # modules.xml 77 | # .idea/misc.xml 78 | # *.ipr 79 | 80 | # Sonarlint plugin 81 | .idea/sonarlint 82 | 83 | ### Kotlin ### 84 | # Compiled class file 85 | *.class 86 | 87 | # Log file 88 | *.log 89 | 90 | # BlueJ files 91 | *.ctxt 92 | 93 | # Mobile Tools for Java (J2ME) 94 | .mtj.tmp/ 95 | 96 | # Package Files # 97 | *.jar 98 | *.war 99 | *.nar 100 | *.ear 101 | *.zip 102 | *.tar.gz 103 | *.rar 104 | 105 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 106 | hs_err_pid* 107 | 108 | ### Gradle ### 109 | .gradle 110 | /build/ 111 | 112 | # Ignore Gradle GUI config 113 | gradle-app.setting 114 | 115 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 116 | !gradle-wrapper.jar 117 | 118 | # Cache of project 119 | .gradletasknamecache 120 | 121 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 122 | # gradle/wrapper/gradle-wrapper.properties 123 | 124 | ### Gradle Patch ### 125 | **/build/ 126 | 127 | # End of https://www.gitignore.io/api/kotlin,gradle,intellij -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018, Greg Hibberd 4 | Copyright (c) 2018, hestia-rsps 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name of the copyright holder nor the names of its 18 | contributors may be used to endorse or promote products derived from 19 | this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Intellij Plugins 2 | 3 | Plugins made for the jetbrains intellij platform. 4 | 5 | ## Deobfuscation 6 | 7 | Tools to support de-obfuscated code refactoring 8 | 9 | | Name | Description | Example | After | 10 | |--|--|--|--| 11 | | Pointless Bitwise Comparator | Simplifies bitwise comparators | `(i ^ 0xffffffff) <= -1` | | `i >= 0` | 12 | | Inverse Else Comparator | Reverses negative if else statements | `if (i != 1) {` | `if (i == 1) {` | 13 | | Inline Nested Else | Inlines else blocks containing if statements | `else { if(...) {` | `else if(...) {` | 14 | 15 | ## Setup 16 | This plugin can now be found on the [Jetbrains Plugin Repository](https://plugins.jetbrains.com/plugin/14101-greg-s-deobsfuscation-tools)! 17 | 18 | See [Managing Plugins](https://www.jetbrains.com/help/idea/managing-plugins.html) for further setup instructions. 19 | 20 | ## Usage 21 | 22 | ### Highlighting 23 | If code in your project code matches one of the tools it will be highlighted 24 | ![code highlight image](https://i.imgur.com/RpHrpvh.png) 25 | 26 | Open the intention actions and quick-fixes menu by pressing the light bulb icon next to the highlighted code (Alt + Enter) 27 | 28 | The intention menu can be used to apply a single quick-fix or by pressing the right arrow key additional options can be selected such as fixing all in a file, module or project. 29 | 30 | ### Search 31 | Inspections can also be ran by name 32 | 33 | `Analyze -> Run inspection by name` (Ctrl + Shift + Alt + I) 34 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.jetbrains.intellij' version '1.13.1' 3 | id 'org.jetbrains.kotlin.jvm' version '1.8.10' 4 | } 5 | 6 | group 'world.gregs.intellij.plugins' 7 | version '1.2.7' 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" 15 | runtimeOnly 'org.jetbrains.kotlin:kotlin-reflect:1.8.10' 16 | } 17 | 18 | compileKotlin { 19 | kotlinOptions.jvmTarget = JavaVersion.VERSION_11 20 | } 21 | 22 | compileTestKotlin { 23 | kotlinOptions.jvmTarget = JavaVersion.VERSION_11 24 | } 25 | 26 | processResources { 27 | from('src/inspectionDescriptions/') { 28 | into 'inspectionDescriptions' 29 | } 30 | } 31 | 32 | intellij { 33 | updateSinceUntilBuild = false 34 | version = "231.8770.65" 35 | type = "IC" 36 | plugins = ["java"] 37 | } 38 | 39 | patchPluginXml { 40 | changeNotes = """ 41 | Updated to support 2023.1 42 | """ 43 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GregHib/intellij-deobfuscation-plugin/6cf11a27adb11f3044a6af833f26f5e1c1bd361d/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'intellij-deobfuscation-plugin' 2 | 3 | -------------------------------------------------------------------------------- /src/inspectionDescriptions/InlineNestedElse.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | This inspection reports when an else statement has a single if statement block which can be inlined, example 'else { if(i == 0) {'
4 | 5 | -------------------------------------------------------------------------------- /src/inspectionDescriptions/InverseElseComparator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | This inspection reports when any else if statements are used with a reversible expression, example 'if(i != 71) { } else { }'
4 | 5 | -------------------------------------------------------------------------------- /src/inspectionDescriptions/PointlessBitwiseComparator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | This inspection reports when any operator is used between bitwise expressions '(i ^ 0xffffffff)' and integer or long types.
4 | 5 | -------------------------------------------------------------------------------- /src/main/kotlin/world/gregs/intellij/plugins/DeobfuscateToolBundle.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins 2 | 3 | import com.intellij.AbstractBundle 4 | import org.jetbrains.annotations.NonNls 5 | import org.jetbrains.annotations.PropertyKey 6 | import java.lang.ref.Reference 7 | import java.lang.ref.SoftReference 8 | import java.util.* 9 | 10 | object DeobfuscateToolBundle { 11 | 12 | private var ourBundle: Reference? = null 13 | @NonNls 14 | const val BUNDLE = "world.gregs.intellij.plugins.DeobfuscateToolBundle" 15 | 16 | private val bundle: ResourceBundle 17 | get() { 18 | var bundle = com.intellij.reference.SoftReference.dereference(ourBundle) 19 | if (bundle == null) { 20 | bundle = ResourceBundle.getBundle(BUNDLE) 21 | ourBundle = SoftReference(bundle) 22 | } 23 | return bundle!! 24 | } 25 | 26 | fun message(@PropertyKey(resourceBundle = BUNDLE) key: String, vararg params: Any): String { 27 | return AbstractBundle.message(bundle, key, *params) 28 | } 29 | } -------------------------------------------------------------------------------- /src/main/kotlin/world/gregs/intellij/plugins/DeobfuscateUtil.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins 2 | 3 | import com.intellij.psi.PsiExpression 4 | import com.siyeh.ig.psiutils.JavaPsiMathUtil 5 | 6 | object DeobfuscateUtil { 7 | fun isNumber(expression: PsiExpression): Boolean { 8 | return JavaPsiMathUtil.getNumberFromLiteral(expression) != null 9 | } 10 | } -------------------------------------------------------------------------------- /src/main/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspection.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins.bitwise 2 | 3 | import com.intellij.codeInspection.ProblemDescriptor 4 | import com.intellij.openapi.project.Project 5 | import com.intellij.psi.* 6 | import com.intellij.psi.JavaTokenType.* 7 | import com.intellij.psi.util.PsiUtil 8 | import com.intellij.psi.util.PsiUtilCore 9 | import com.intellij.util.containers.ContainerUtil 10 | import com.siyeh.ig.BaseInspection 11 | import com.siyeh.ig.BaseInspectionVisitor 12 | import com.siyeh.ig.InspectionGadgetsFix 13 | import com.siyeh.ig.psiutils.CommentTracker 14 | import com.siyeh.ig.psiutils.ComparisonUtils 15 | import com.siyeh.ig.psiutils.JavaPsiMathUtil 16 | import org.jetbrains.annotations.NonNls 17 | import world.gregs.intellij.plugins.DeobfuscateToolBundle 18 | import world.gregs.intellij.plugins.DeobfuscateUtil.isNumber 19 | 20 | class PointlessBitwiseComparatorInspection : BaseInspection() { 21 | 22 | override fun getDisplayName(): String { 23 | return DeobfuscateToolBundle.message("pointless.bitwise.comparator.display.name") 24 | } 25 | 26 | public override fun buildErrorString(vararg infos: Any): String { 27 | val expression = infos[0] as PsiExpression 28 | val replacementExpression = calculateReplacementExpression(expression) 29 | return DeobfuscateToolBundle.message("expression.can.be.replaced.problem.descriptor", replacementExpression) 30 | } 31 | 32 | override fun isEnabledByDefault(): Boolean { 33 | return true 34 | } 35 | 36 | @NonNls 37 | internal fun calculateReplacementExpression(expression: PsiExpression): String { 38 | if (expression !is PsiBinaryExpression) { 39 | return "" 40 | } 41 | val operator = expression.operationSign 42 | val left = expression.lOperand 43 | val right = expression.rOperand ?: return "" 44 | 45 | val ct = CommentTracker() 46 | 47 | if (isBitwiseOperator(left) && isBitwiseOperator(right)) { 48 | val lOperand = getOperandText(left, ct) 49 | val rOperand = getOperandText(right, ct) 50 | if (lOperand != null && rOperand != null) { 51 | return "$rOperand ${ct.text(operator)} $lOperand" 52 | } 53 | } else if (isBitwiseOperator(left) && isNumber(right) || isNumber(left) && isBitwiseOperator(right)) { 54 | val flip = isNumber(left) && isBitwiseOperator(right) 55 | val number = JavaPsiMathUtil.getNumberFromLiteral(if (flip) left else right) 56 | val operand = getOperandText(if (flip) right else left, ct) 57 | if (number != null && operand != null) { 58 | val flipped = when (operator.tokenType) { 59 | GT, GE, LT, LE -> ComparisonUtils.getFlippedComparison(operator.tokenType) 60 | else -> ct.text(operator) 61 | } 62 | return "$operand ${if (flip) ct.text(operator) else flipped} ${decrementReverseValue(number)}" 63 | } 64 | } else { 65 | throw IllegalStateException("Didn't expect to see you here.") 66 | } 67 | return "" 68 | } 69 | 70 | override fun buildVisitor(): BaseInspectionVisitor { 71 | return object : BaseInspectionVisitor() { 72 | 73 | override fun visitPolyadicExpression(expression: PsiPolyadicExpression) { 74 | super.visitPolyadicExpression(expression) 75 | val sign = expression.operationTokenType 76 | 77 | if (!comparisonTokens.contains(sign)) { 78 | return 79 | } 80 | 81 | if (PsiUtilCore.hasErrorElementChild(expression)) { 82 | return 83 | } 84 | 85 | val operands = expression.operands 86 | val parenthesized = operands.filter { it is PsiParenthesizedExpression || it is PsiPrefixExpression } 87 | 88 | //Must have at least one bitwise operator 89 | val bitwise = parenthesized.any { isBitwiseOperator(it) } 90 | if (!bitwise) { 91 | return 92 | } 93 | 94 | //Either two bitwise or a bitwise and a number 95 | val bitwiseCount = parenthesized.count { isBitwiseOperator(it) } 96 | if (bitwiseCount != 2) { 97 | val number = operands.any { isNumber(it) } 98 | 99 | if (!number) { 100 | return 101 | } 102 | } 103 | 104 | registerError(expression, expression) 105 | } 106 | } 107 | } 108 | 109 | public override fun buildFix(vararg infos: Any): InspectionGadgetsFix { 110 | return object : InspectionGadgetsFix() { 111 | 112 | override fun getFamilyName(): String { 113 | return DeobfuscateToolBundle.message("pointless.bitwise.comparator.simplify.quickfix") 114 | } 115 | 116 | public override fun doFix(project: Project, descriptor: ProblemDescriptor) { 117 | val expression = descriptor.psiElement as PsiExpression 118 | val ct = CommentTracker() 119 | val newExpression = calculateReplacementExpression(expression) 120 | if (newExpression.isNotEmpty()) { 121 | ct.replaceAndRestoreComments(expression, newExpression) 122 | } 123 | } 124 | } 125 | } 126 | 127 | companion object { 128 | internal val comparisonTokens = ContainerUtil.immutableSet(EQEQ, NE, LT, GT, LE, GE) 129 | 130 | private fun decrementReverseValue(number: Number): String { 131 | val decremented = -number.toLong() - 1 132 | return if (decremented > Int.MAX_VALUE || decremented < Int.MIN_VALUE) { 133 | "${decremented}L" 134 | } else { 135 | decremented.toString() 136 | } 137 | } 138 | 139 | private fun isHex(expression: PsiExpression?): Boolean { 140 | return expression != null && (expression.type == PsiTypes.intType() && expression.text == "0xffffffff" || expression.type == PsiTypes.longType() && expression.text == "0xffffffffffffffffL") 141 | } 142 | 143 | private fun isBitwiseOperator(express: PsiExpression?): Boolean { 144 | when (val expression = if (express is PsiParenthesizedExpression) PsiUtil.skipParenthesizedExprDown(express) else express) { 145 | is PsiPrefixExpression -> { 146 | if (expression.operationTokenType == TILDE) { 147 | return true 148 | } 149 | } 150 | is PsiBinaryExpression -> { 151 | val sign = expression.operationTokenType 152 | 153 | if (sign != XOR) { 154 | return false 155 | } 156 | 157 | if (isHex(expression.lOperand) || isHex(expression.rOperand)) { 158 | return true 159 | } 160 | } 161 | } 162 | return false 163 | } 164 | 165 | private fun getOperandText(expression: PsiExpression, ct: CommentTracker): String? { 166 | val express = PsiUtil.skipParenthesizedExprDown(expression) ?: return null 167 | val operand: PsiExpression? = when (express) { 168 | is PsiPrefixExpression -> { 169 | var child = express.lastChild as? PsiExpression 170 | if (child is PsiParenthesizedExpression) { 171 | child = PsiUtil.skipParenthesizedExprDown(child) 172 | } 173 | PsiUtil.skipParenthesizedExprDown(child) ?: return null 174 | } 175 | is PsiBinaryExpression -> { 176 | when { 177 | isHex(express.lOperand) -> express.rOperand 178 | isHex(express.rOperand) -> express.lOperand 179 | else -> null 180 | } 181 | } 182 | else -> null 183 | } 184 | //AND operators still require parentheses 185 | return if (operand is PsiPolyadicExpression && operand.operationTokenType == AND) { 186 | "(${ct.text(operand)})" 187 | } else if (operand != null) { 188 | ct.text(operand) 189 | } else { 190 | null 191 | } 192 | } 193 | } 194 | } -------------------------------------------------------------------------------- /src/main/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspection.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins.flow 2 | 3 | import com.intellij.codeInspection.ProblemDescriptor 4 | import com.intellij.openapi.project.Project 5 | import com.intellij.openapi.util.Pair 6 | import com.intellij.psi.* 7 | import com.intellij.psi.codeStyle.CodeStyleManager 8 | import com.intellij.psi.util.PsiTreeUtil 9 | import com.intellij.psi.util.PsiUtilCore 10 | import com.siyeh.ig.BaseInspectionVisitor 11 | import com.siyeh.ig.InspectionGadgetsFix 12 | import com.siyeh.ig.psiutils.CommentTracker 13 | import com.siyeh.ig.style.ControlFlowStatementVisitorBase 14 | import com.siyeh.ig.style.SingleStatementInBlockInspection 15 | import org.jetbrains.annotations.Nls 16 | import org.jetbrains.annotations.NotNull 17 | import world.gregs.intellij.plugins.DeobfuscateToolBundle 18 | 19 | class InlineNestedElseInspection : SingleStatementInBlockInspection() { 20 | 21 | override fun getDisplayName(): String { 22 | return DeobfuscateToolBundle.message("inline.nested.else.display.name") 23 | } 24 | 25 | public override fun buildErrorString(vararg infos: Any): String { 26 | return DeobfuscateToolBundle.message("inline.nested.else.problem.descriptor") 27 | } 28 | 29 | override fun isEnabledByDefault(): Boolean { 30 | return true 31 | } 32 | 33 | override fun buildVisitor(): BaseInspectionVisitor { 34 | return object : ControlFlowStatementVisitorBase() { 35 | override fun isApplicable(body: PsiStatement?): Boolean { 36 | //If body is else branch of parent 37 | val parent = body?.parent 38 | if (body is PsiBlockStatement && parent is PsiIfStatement && parent.elseBranch == body) { 39 | val codeBlock = body.codeBlock 40 | if (PsiUtilCore.hasErrorElementChild(codeBlock)) { 41 | return false 42 | } 43 | 44 | //Else block must only contain a single if statement 45 | val statement = codeBlock.statements.firstOrNull() 46 | if (codeBlock.statementCount == 1 && statement is PsiIfStatement) { 47 | if (PsiUtilCore.hasErrorElementChild(statement)) { 48 | return false 49 | } 50 | return true 51 | } 52 | } 53 | return false 54 | } 55 | 56 | override fun getOmittedBodyBounds(body: PsiStatement?): Pair? { 57 | if (body is PsiBlockStatement) { 58 | val codeBlock = body.codeBlock 59 | if (codeBlock.statementCount == 1) { 60 | val statement = codeBlock.statements.firstOrNull() 61 | if (statement?.textContains('\n') == true) { 62 | return Pair(statement, statement) 63 | } 64 | } 65 | } 66 | return null 67 | } 68 | 69 | } 70 | } 71 | 72 | override fun buildFix(vararg infos: Any?): InspectionGadgetsFix { 73 | return object : InspectionGadgetsFix() { 74 | @Nls 75 | @NotNull 76 | override fun getName(): String { 77 | return DeobfuscateToolBundle.message("inline.nested.else.quickfix") 78 | } 79 | 80 | @Nls 81 | @NotNull 82 | override fun getFamilyName(): String { 83 | return DeobfuscateToolBundle.message("inline.nested.else.family.quickfix") 84 | } 85 | 86 | override fun doFix(project: Project, descriptor: ProblemDescriptor) { 87 | var statement = PsiTreeUtil.getNonStrictParentOfType(descriptor.startElement, PsiStatement::class.java) 88 | ?: return 89 | 90 | if (statement is PsiBlockStatement) { 91 | statement = PsiTreeUtil.getNonStrictParentOfType(statement.parent, PsiStatement::class.java) 92 | ?: return 93 | } 94 | 95 | val body = when (statement) { 96 | is PsiLoopStatement -> statement.body 97 | is PsiIfStatement -> statement.elseBranch 98 | else -> null 99 | } as? PsiBlockStatement ?: return 100 | 101 | val child = body.codeBlock.statements.firstOrNull() 102 | if (body.codeBlock.statementCount != 1 || child == null) { 103 | return 104 | } 105 | 106 | val ct = CommentTracker() 107 | val text = ct.text(child) 108 | val replacementExp = ct.replace(body, text) 109 | CodeStyleManager.getInstance(project).reformat(replacementExp) 110 | ct.insertCommentsBefore(statement) 111 | } 112 | } 113 | } 114 | } -------------------------------------------------------------------------------- /src/main/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspection.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins.flow 2 | 3 | import com.intellij.codeInspection.ProblemDescriptor 4 | import com.intellij.openapi.project.Project 5 | import com.intellij.psi.* 6 | import com.intellij.psi.JavaTokenType.* 7 | import com.intellij.psi.util.PsiUtil 8 | import com.intellij.util.containers.ContainerUtil 9 | import com.siyeh.ig.BaseInspection 10 | import com.siyeh.ig.BaseInspectionVisitor 11 | import com.siyeh.ig.InspectionGadgetsFix 12 | import com.siyeh.ig.PsiReplacementUtil 13 | import com.siyeh.ig.psiutils.CommentTracker 14 | import com.siyeh.ig.psiutils.ComparisonUtils 15 | import org.jetbrains.annotations.NonNls 16 | import world.gregs.intellij.plugins.DeobfuscateToolBundle 17 | 18 | class InverseElseComparatorInspection : BaseInspection() { 19 | 20 | override fun getDisplayName(): String { 21 | return DeobfuscateToolBundle.message("inverse.else.comparator.display.name") 22 | } 23 | 24 | public override fun buildErrorString(vararg infos: Any): String { 25 | val expression = infos[0] as PsiExpression 26 | val statement = infos[1] as PsiIfStatement 27 | val ct = CommentTracker() 28 | val replacement = calculateReplacementExpression(statement, ct) 29 | return DeobfuscateToolBundle.message( 30 | "comparator.can.be.inverted.problem.descriptor", 31 | ct.text(expression), 32 | replacement 33 | ) 34 | } 35 | 36 | override fun isEnabledByDefault(): Boolean { 37 | return true 38 | } 39 | 40 | override fun buildVisitor(): BaseInspectionVisitor { 41 | return object : BaseInspectionVisitor() { 42 | override fun visitIfStatement(statement: PsiIfStatement) { 43 | super.visitIfStatement(statement) 44 | 45 | //Must have else block statement 46 | if (statement.elseBranch !is PsiBlockStatement) { 47 | return 48 | } 49 | 50 | val expression = statement.condition 51 | when (expression) { 52 | is PsiPrefixExpression -> { 53 | val child = expression.lastChild 54 | //Check is exclamation boolean 55 | if (expression.operationTokenType != EXCL || (child !is PsiReferenceExpression && child !is PsiParenthesizedExpression && child !is PsiMethodCallExpression)) { 56 | return 57 | } 58 | } 59 | is PsiPolyadicExpression -> { 60 | //If binary do single & range check 61 | if (expression is PsiBinaryExpression) { 62 | //Check expression has operands 63 | val left = expression.lOperand 64 | val right = expression.rOperand 65 | ?: return 66 | 67 | //Check both operands are binary expressions that have a range operation type 68 | val valid = when (expression.operationTokenType) { 69 | //Single operand 70 | NE -> true 71 | //Both operands are binary expressions that have a range operation type 72 | OROR -> left is PsiBinaryExpression && right is PsiBinaryExpression && comparisonTokens.contains(left.operationTokenType) && comparisonTokens.contains(right.operationTokenType) 73 | else -> false 74 | } 75 | 76 | if (valid) { 77 | registerError(statement, expression, statement) 78 | return 79 | } 80 | } 81 | 82 | //Check all operands are joined by '&&' and are negative 83 | expression.operands.forEach { 84 | val token = expression.getTokenBeforeOperand(it)?.tokenType 85 | if (token == null || token == ANDAND) { 86 | //Only continue if negated 87 | if (it is PsiPrefixExpression && it.operationTokenType == EXCL) { 88 | return@forEach 89 | } else if (it is PsiBinaryExpression && it.operationTokenType == NE) { 90 | return@forEach 91 | } 92 | } 93 | return 94 | } 95 | } 96 | else -> return 97 | } 98 | registerError(statement, expression, statement) 99 | } 100 | } 101 | } 102 | 103 | public override fun buildFix(vararg infos: Any): InspectionGadgetsFix { 104 | return object : InspectionGadgetsFix() { 105 | 106 | override fun getFamilyName(): String { 107 | return DeobfuscateToolBundle.message("inverse.else.comparator.invert.quickfix") 108 | } 109 | 110 | public override fun doFix(project: Project, descriptor: ProblemDescriptor) { 111 | val statement = descriptor.psiElement as PsiIfStatement 112 | 113 | val expression = statement.condition 114 | if (expression is PsiPrefixExpression || expression is PsiBinaryExpression) { 115 | val ct = CommentTracker() 116 | 117 | //Replace expression with negative comparator 118 | val expected = calculateReplacementExpression(statement, ct) 119 | if (expected.isEmpty()) { 120 | throw IllegalStateException("Empty replacement for $statement $expression") 121 | } else { 122 | PsiReplacementUtil.replaceExpression(expression, expected, ct) 123 | } 124 | 125 | //Switch branches 126 | val branch = statement.thenBranch 127 | val elseBranch = statement.elseBranch?.copy() as? PsiStatement 128 | if (branch != null) { 129 | statement.setElseBranch(branch) 130 | } 131 | if (elseBranch != null) { 132 | statement.setThenBranch(elseBranch) 133 | } 134 | } 135 | return 136 | } 137 | } 138 | } 139 | 140 | @NonNls 141 | internal fun calculateReplacementExpression(statement: PsiIfStatement, ct: CommentTracker): String { 142 | return when (val expression = statement.condition) { 143 | is PsiPrefixExpression -> { 144 | var child = expression.lastChild 145 | if (child is PsiParenthesizedExpression) { 146 | child = PsiUtil.deparenthesizeExpression(child) 147 | } 148 | ct.text(child) 149 | } 150 | is PsiPolyadicExpression -> { 151 | //If binary check single & range 152 | if (expression is PsiBinaryExpression) { 153 | when (val sign = expression.operationTokenType) { 154 | NE -> return replaceOperation(expression, ComparisonUtils.getNegatedComparison(sign), ct) 155 | OROR -> { 156 | //Get operands as expressions 157 | val left = expression.lOperand as? PsiBinaryExpression 158 | ?: return "" 159 | val right = expression.rOperand as? PsiBinaryExpression 160 | ?: return "" 161 | //Replace expressions with negated operators 162 | val leftNew = replaceOperation(left, ComparisonUtils.getNegatedComparison(left.operationTokenType), ct) 163 | val rightNew = replaceOperation(right, ComparisonUtils.getNegatedComparison(right.operationTokenType), ct) 164 | //Change statement operator 165 | val opposite = when (sign) { 166 | OROR -> "&&" 167 | ANDAND -> "||" 168 | else -> throw IllegalStateException() 169 | } 170 | return "$leftNew $opposite $rightNew" 171 | } 172 | } 173 | } 174 | val builder = StringBuilder() 175 | //Apply each operand, negating operators and removing negative prefixes 176 | expression.operands.forEach { 177 | //Apply logical operators 178 | val token = expression.getTokenBeforeOperand(it) 179 | if (token != null) { 180 | builder.append(" || ") 181 | } 182 | 183 | //Apply operands 184 | if (it is PsiPrefixExpression) { 185 | //Ignore prefix 186 | builder.append(ct.text(it.lastChild)) 187 | } else if (it is PsiBinaryExpression) { 188 | //Negate relational operators 189 | builder.append(replaceOperation(it, ComparisonUtils.getNegatedComparison(it.operationTokenType), ct)) 190 | } 191 | } 192 | builder.toString() 193 | } 194 | else -> "" 195 | } 196 | } 197 | 198 | /** 199 | * Replaces [expression] operator 200 | * @param expression The binary expression who's operator to replace 201 | * @param operator The new operator 202 | * @param ct CommentTracker 203 | * @return [expression] as a string with the new [operator] 204 | */ 205 | private fun replaceOperation(expression: PsiBinaryExpression, operator: String, ct: CommentTracker): String { 206 | return "${ct.text(expression.lOperand)} $operator ${ct.text(expression.rOperand!!)}" 207 | } 208 | 209 | companion object { 210 | internal val comparisonTokens = ContainerUtil.immutableSet(LT, GT, LE, GE) 211 | } 212 | } -------------------------------------------------------------------------------- /src/main/resources/META-INF/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | world.gregs.intellij.plugins.deobfuscation 3 | Greg's Deobsfuscation Tools 4 | Greg 5 | 6 | A few intellij plugins to assist refactoring obfuscated code 7 | 8 | 10 | 13 | 14 | 15 | com.intellij.modules.java 16 | 17 | 18 | 23 | 28 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/main/resources/world/gregs/intellij/plugins/DeobfuscateToolBundle.properties: -------------------------------------------------------------------------------- 1 | pointless.bitwise.comparator.display.name=Pointless bitwise comparator 2 | expression.can.be.replaced.problem.descriptor=#ref can be replaced with ''{0}'' #loc 3 | pointless.bitwise.comparator.simplify.quickfix=Simplify 4 | 5 | inverse.else.comparator.display.name=Inverse if else comparator 6 | comparator.can.be.inverted.problem.descriptor=''{0}'' can be inverted to ''{1}'' #loc 7 | inverse.else.comparator.invert.quickfix=Invert 8 | 9 | inline.nested.else.display.name=Inline nested else statement 10 | inline.nested.else.problem.descriptor=#ref can be inlined #loc 11 | inline.nested.else.quickfix=Inline 'else' statement 12 | inline.nested.else.family.quickfix=Inline statements 13 | -------------------------------------------------------------------------------- /src/test/kotlin/world/gregs/intellij/plugins/LightInspectionTester.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins 2 | 3 | import com.intellij.codeHighlighting.HighlightDisplayLevel 4 | import com.intellij.codeInsight.daemon.HighlightDisplayKey 5 | import com.intellij.profile.codeInspection.ProjectInspectionProfileManager 6 | import com.intellij.testFramework.UsefulTestCase 7 | import org.intellij.lang.annotations.Language 8 | import org.junit.Assert 9 | 10 | /** 11 | * Clone of [LightInspectionTestCase] 12 | * @author Bas Leijdekkers 13 | */ 14 | abstract class LightInspectionTester : LightTester(false) { 15 | 16 | @Throws(Exception::class) 17 | override fun setUp() { 18 | super.setUp() 19 | 20 | val inspection = getInspection() 21 | if (inspection != null) { 22 | val project = myFixture.project 23 | val displayKey = HighlightDisplayKey.find(inspection.shortName) 24 | val currentProfile = ProjectInspectionProfileManager.getInstance(project).currentProfile 25 | val errorLevel = currentProfile.getErrorLevel(displayKey, null) 26 | if (errorLevel === HighlightDisplayLevel.DO_NOT_SHOW) { 27 | currentProfile.setErrorLevel(displayKey, HighlightDisplayLevel.WARNING, project) 28 | } 29 | } 30 | } 31 | 32 | protected fun addEnvironmentClass(@Language("JAVA") classText: String) { 33 | myFixture.addClass(classText) 34 | } 35 | 36 | protected fun doStatementTest(@Language(value = "JAVA", prefix = "@SuppressWarnings(\"all\") class X { void m() {", suffix = "}}") statementText: String) { 37 | doTest("class X { void m() {$statementText}}") 38 | } 39 | 40 | protected fun doMemberTest(@Language(value = "JAVA", prefix = "@SuppressWarnings(\"all\") class X {", suffix = "}") memberText: String) { 41 | doTest("class X {$memberText}") 42 | } 43 | 44 | protected fun doTest(@Language("JAVA") classText: String) { 45 | doTest(classText, "X.java") 46 | } 47 | 48 | protected fun assertQuickFixNotAvailable(name: String) { 49 | UsefulTestCase.assertEmpty(myFixture.filterAvailableIntentions(name)) 50 | } 51 | 52 | protected fun checkQuickFix(name: String, @Language("JAVA") result: String) { 53 | val intention = myFixture.getAvailableIntention(name) 54 | Assert.assertNotNull(intention) 55 | myFixture.launchAction(intention!!) 56 | myFixture.checkResult(result) 57 | } 58 | 59 | protected fun checkQuickFix(intentionName: String) { 60 | val intention = myFixture.getAvailableIntention(intentionName) 61 | Assert.assertNotNull(intention) 62 | myFixture.launchAction(intention!!) 63 | myFixture.checkResultByFile(getTestName(false) + ".after.java") 64 | } 65 | 66 | protected fun doTest(@Language("JAVA") classText: String, fileName: String) { 67 | val newText = StringBuilder() 68 | var start = 0 69 | var end = classText.indexOf("/*") 70 | while (end >= 0) { 71 | newText.append(classText, start, end) 72 | start = end + 2 73 | end = classText.indexOf("*/", end) 74 | if (end < 0) { 75 | throw IllegalArgumentException("invalid class text") 76 | } 77 | val text = classText.substring(start, end) 78 | when { 79 | text.isEmpty() -> newText.append("") 80 | "!" == text -> newText.append("") 81 | "_" == text -> newText.append("") 82 | text.startsWith("!") -> newText.append("") 83 | text.startsWith(" ") -> newText.append("/*").append(text).append("*/") 84 | else -> newText.append("") 85 | } 86 | start = end + 2 87 | end = classText.indexOf("/*", end + 1) 88 | } 89 | newText.append(classText, start, classText.length) 90 | myFixture.configureByText(fileName, newText.toString()) 91 | myFixture.testHighlighting(true, false, false) 92 | } 93 | 94 | protected fun doTest() { 95 | doNamedTest(getTestName(false)) 96 | } 97 | 98 | protected fun doNamedTest(name: String) { 99 | myFixture.configureByFile("$name.java") 100 | myFixture.testHighlighting(true, false, false) 101 | } 102 | 103 | } -------------------------------------------------------------------------------- /src/test/kotlin/world/gregs/intellij/plugins/LightQuickFixTester.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins 2 | 3 | import com.intellij.ide.highlighter.JavaFileType 4 | import com.intellij.pom.java.LanguageLevel 5 | import com.intellij.testFramework.UsefulTestCase 6 | import com.intellij.testFramework.builders.JavaModuleFixtureBuilder 7 | import org.intellij.lang.annotations.Language 8 | import org.jetbrains.annotations.NonNls 9 | import org.junit.Assert 10 | import java.nio.file.FileSystems 11 | 12 | /** 13 | * Clone of [com.siyeh.ig.IGQuickFixesTestCase] 14 | * @author anna 15 | */ 16 | abstract class LightQuickFixTester : LightTester(true) { 17 | abstract val myDefaultHint: String 18 | 19 | @Throws(Exception::class) 20 | override fun tuneFixture(builder: JavaModuleFixtureBuilder<*>?) { 21 | builder!!.setLanguageLevel(LanguageLevel.JDK_1_8) 22 | } 23 | 24 | override fun getTestDataPath(): String { 25 | return "${FileSystems.getDefault().getPath("").toAbsolutePath()}/src/test/resources/fixes/$basePath" 26 | } 27 | 28 | protected fun assertQuickfixNotAvailable() { 29 | assertQuickfixNotAvailable(myDefaultHint) 30 | } 31 | 32 | protected fun assertQuickfixNotAvailable(quickfixName: String?) { 33 | val testName = getTestName(false) 34 | myFixture.configureByFile("$testName.java") 35 | UsefulTestCase.assertEmpty("Quickfix \'$quickfixName\' is available but should not", 36 | myFixture.filterAvailableIntentions(quickfixName!!)) 37 | } 38 | 39 | protected fun assertQuickfixNotAvailable(quickfixName: String, @Language("JAVA") @NonNls text: String) { 40 | var text = text 41 | text = text.replace("/**/", "") 42 | myFixture.configureByText(JavaFileType.INSTANCE, text) 43 | UsefulTestCase.assertEmpty("Quickfix \'$quickfixName\' is available but should not", 44 | myFixture.filterAvailableIntentions(quickfixName)) 45 | } 46 | 47 | protected fun doTest() { 48 | val testName = getTestName(false) 49 | doTest(testName, myDefaultHint) 50 | } 51 | 52 | protected fun doTest(hint: String) { 53 | val testName = getTestName(false) 54 | doTest(testName, hint) 55 | } 56 | 57 | protected fun doTest(testName: String, hint: String) { 58 | myFixture.configureByFile("$testName.java") 59 | val action = myFixture.getAvailableIntention(hint) 60 | Assert.assertNotNull(action) 61 | myFixture.launchAction(action!!) 62 | myFixture.checkResultByFile("$testName.after.java") 63 | } 64 | 65 | protected fun doExpressionTest( 66 | hint: String, 67 | @Language(value = "JAVA", prefix = "/** @noinspection ALL*/class \$X$ {static {System.out.print(", suffix = ");}}") @NonNls before: String, 68 | @Language(value = "JAVA", prefix = "class \$X$ {static {System.out.print(", suffix = ");}}") @NonNls after: String) { 69 | doTest(hint, "class \$X$ {static {System.out.print($before);}}", "class \$X$ {static {System.out.print($after);}}") 70 | } 71 | 72 | protected fun doMemberTest( 73 | hint: String, 74 | @Language(value = "JAVA", prefix = "/** @noinspection ALL*/class \$X$ {", suffix = "}") @NonNls before: String, 75 | @Language(value = "JAVA", prefix = "class \$X$ {", suffix = "}") @NonNls after: String) { 76 | doTest(hint, "class \$X$ {$before}", "class \$X$ {$after}") 77 | } 78 | 79 | protected fun doTest(hint: String, 80 | @Language("JAVA") @NonNls before: String, 81 | @Language("JAVA") @NonNls after: String) { 82 | doTest(hint, before, after, "aaa.java") 83 | } 84 | 85 | protected fun doTest(hint: String, 86 | @Language("JAVA") @NonNls before: String, 87 | @Language("JAVA") @NonNls after: String, 88 | fileName: String) { 89 | var before = before 90 | before = before.replace("/**/", "") 91 | myFixture.configureByText(fileName, before) 92 | val intention = myFixture.getAvailableIntention(hint) 93 | Assert.assertNotNull(intention) 94 | myFixture.launchAction(intention!!) 95 | myFixture.checkResult(after) 96 | } 97 | 98 | } -------------------------------------------------------------------------------- /src/test/kotlin/world/gregs/intellij/plugins/LightTester.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins 2 | 3 | import com.intellij.codeInspection.InspectionProfileEntry 4 | import com.intellij.openapi.util.text.StringUtil 5 | import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase 6 | import com.siyeh.ig.BaseInspection 7 | import org.junit.Assert 8 | import java.nio.file.FileSystems 9 | 10 | abstract class LightTester(private val fix: Boolean) : JavaCodeInsightFixtureTestCase() { 11 | 12 | @Throws(Exception::class) 13 | override fun setUp() { 14 | super.setUp() 15 | 16 | val inspections = getInspections() 17 | if (inspections != null) { 18 | myFixture.enableInspections(*inspections) 19 | } 20 | } 21 | 22 | private fun getInspections(): Array? { 23 | val inspection = getInspection() 24 | return inspection?.let { arrayOf(it) } 25 | } 26 | 27 | abstract fun getInspection(): BaseInspection? 28 | 29 | override fun getTestDataPath(): String { 30 | return "${FileSystems.getDefault().getPath("").toAbsolutePath()}/src/test/resources/${if (fix) "fixes" else "test"}/$basePath" 31 | } 32 | 33 | override fun getBasePath(): String { 34 | val className = getInspectionClass().name 35 | val words = className.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() 36 | val basePath = StringBuilder() 37 | val lastWordIndex = words.size - 1 38 | for (i in 0 until lastWordIndex) { 39 | basePath.append(words[i]).append('/') 40 | } 41 | var lastWord = words[lastWordIndex] 42 | lastWord = StringUtil.trimEnd(lastWord, "Inspection") 43 | val length = lastWord.length 44 | var upperCase = false 45 | for (i in 0 until length) { 46 | val ch = lastWord[i] 47 | if (Character.isUpperCase(ch)) { 48 | if (!upperCase) { 49 | upperCase = true 50 | if (i != 0) { 51 | basePath.append('_') 52 | } 53 | } 54 | basePath.append(Character.toLowerCase(ch)) 55 | } else { 56 | upperCase = false 57 | basePath.append(ch) 58 | } 59 | } 60 | return basePath.toString() 61 | } 62 | 63 | protected fun getInspectionClass(): Class { 64 | val inspection = getInspection() 65 | Assert.assertNotNull("File-based tests should either return an inspection or override this method", inspection) 66 | return inspection!!.javaClass 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /src/test/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorFixTest.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins.bitwise 2 | 3 | import com.siyeh.ig.BaseInspection 4 | import world.gregs.intellij.plugins.DeobfuscateToolBundle 5 | import world.gregs.intellij.plugins.LightQuickFixTester 6 | 7 | internal class PointlessBitwiseComparatorFixTest : LightQuickFixTester() { 8 | 9 | override val myDefaultHint = DeobfuscateToolBundle.message("pointless.bitwise.comparator.simplify.quickfix") 10 | 11 | fun testRemoveBitwiseAndComparator() { 12 | doTest() 13 | } 14 | 15 | fun testRemoveBitwiseComparator() { 16 | doTest() 17 | } 18 | 19 | fun testRemoveComplimentAndComparator() { 20 | doTest() 21 | } 22 | 23 | fun testRemoveComplimentComparator() { 24 | doTest() 25 | } 26 | 27 | fun testRemoveFlippedBitwiseComparator() { 28 | doTest() 29 | } 30 | 31 | override fun getInspection(): BaseInspection { 32 | return PointlessBitwiseComparatorInspection() 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /src/test/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspectionTest.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins.bitwise 2 | 3 | import com.siyeh.ig.BaseInspection 4 | import world.gregs.intellij.plugins.LightInspectionTester 5 | 6 | internal class PointlessBitwiseComparatorInspectionTest : LightInspectionTester() { 7 | 8 | fun testPointlessBitwiseComparator() { 9 | doTest() 10 | } 11 | 12 | fun testTildeComparator() { 13 | doTest() 14 | } 15 | 16 | fun testIgnoredComparators() { 17 | doTest() 18 | } 19 | 20 | fun testLessThanBitwiseComparator() { 21 | doTest() 22 | } 23 | 24 | fun testLessThanEqualBitwiseComparator() { 25 | doTest() 26 | } 27 | 28 | fun testGreaterThanBitwiseComparator() { 29 | doTest() 30 | } 31 | 32 | fun testGreaterThanEqualBitwiseComparator() { 33 | doTest() 34 | } 35 | 36 | fun testEqualsBitwiseComparator() { 37 | doTest() 38 | } 39 | 40 | fun testNotEqualsBitwiseComparator() { 41 | doTest() 42 | } 43 | 44 | override fun getInspection(): BaseInspection { 45 | return PointlessBitwiseComparatorInspection() 46 | } 47 | } -------------------------------------------------------------------------------- /src/test/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseFixTest.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins.flow 2 | 3 | import com.siyeh.ig.BaseInspection 4 | import world.gregs.intellij.plugins.DeobfuscateToolBundle 5 | import world.gregs.intellij.plugins.LightQuickFixTester 6 | 7 | internal class InlineNestedElseFixTest : LightQuickFixTester() { 8 | override val myDefaultHint = DeobfuscateToolBundle.message("inline.nested.else.quickfix") 9 | 10 | fun testInlineNestedElse() { 11 | doTest() 12 | } 13 | 14 | fun testInlineNestedElseBoolean() { 15 | doTest() 16 | } 17 | 18 | fun testInlineNestedElseMethod() { 19 | doTest() 20 | } 21 | 22 | override fun getInspection(): BaseInspection { 23 | return InlineNestedElseInspection() 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspectionTest.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins.flow 2 | 3 | import com.siyeh.ig.BaseInspection 4 | import world.gregs.intellij.plugins.LightInspectionTester 5 | 6 | internal class InlineNestedElseInspectionTest : LightInspectionTester() { 7 | 8 | fun testNestedElse() { 9 | doTest() 10 | } 11 | 12 | override fun getInspection(): BaseInspection { 13 | return InlineNestedElseInspection() 14 | } 15 | } -------------------------------------------------------------------------------- /src/test/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorFixTest.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins.flow 2 | 3 | import com.siyeh.ig.BaseInspection 4 | import world.gregs.intellij.plugins.DeobfuscateToolBundle 5 | import world.gregs.intellij.plugins.LightQuickFixTester 6 | 7 | internal class InverseElseComparatorFixTest : LightQuickFixTester() { 8 | override val myDefaultHint = DeobfuscateToolBundle.message("inverse.else.comparator.invert.quickfix") 9 | 10 | fun testInvertSingleElseComparator() { 11 | doTest() 12 | } 13 | 14 | fun testInvertDoubleElseComparator() { 15 | doTest() 16 | } 17 | 18 | fun testInvertMethodElseComparator() { 19 | doTest() 20 | } 21 | 22 | fun testInvertRangeElseComparator() { 23 | doTest() 24 | } 25 | 26 | override fun getInspection(): BaseInspection { 27 | return InverseElseComparatorInspection() 28 | } 29 | } -------------------------------------------------------------------------------- /src/test/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspectionTest.kt: -------------------------------------------------------------------------------- 1 | package world.gregs.intellij.plugins.flow 2 | 3 | import com.siyeh.ig.BaseInspection 4 | import world.gregs.intellij.plugins.LightInspectionTester 5 | 6 | internal class InverseElseComparatorInspectionTest : LightInspectionTester() { 7 | 8 | fun testInverseElseComparator() { 9 | doTest() 10 | } 11 | 12 | fun testInverseBooleanComparator() { 13 | doTest() 14 | } 15 | 16 | fun testInverseMethodComparator() { 17 | doTest() 18 | } 19 | 20 | fun testInverseRangeComparator() { 21 | doTest() 22 | } 23 | 24 | override fun getInspection(): BaseInspection { 25 | return InverseElseComparatorInspection() 26 | } 27 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseAndComparator.after.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | 5 | public void method() { 6 | boolean result = (0x400 & first) == 0; 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseAndComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | 5 | public void method() { 6 | boolean result = (0x400 & first ^ 0xffffffff) == -1; 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseComparator.after.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | 5 | public void method() { 6 | boolean result = first > 32767; 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | 5 | public void method() { 6 | boolean result = (first ^ 0xffffffff) < -32768; 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentAndComparator.after.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | 5 | public void method() { 6 | boolean result = (first & 0x400) == 0; 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentAndComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | 5 | public void method() { 6 | boolean result = ~(first & 0x400) == -1; 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentComparator.after.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | private int[] is = new int[1]; 6 | 7 | public void method() { 8 | boolean result = (first ^ 0xffffffff) > -36 && is[second - -1] != 0; 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | private int[] is = new int[1]; 6 | 7 | public void method() { 8 | boolean result = (first ^ 0xffffffff) > -36 && ~is[second - -1] != -1; 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveFlippedBitwiseComparator.after.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | 5 | public void method() { 6 | boolean result = first + 4 <= 0; 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveFlippedBitwiseComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | 5 | public void method() { 6 | boolean result = -1 <= (0xffffffff ^ first + 4); 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElse.after.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void method() { 7 | if (first == 1) { 8 | second = 1; 9 | } else if (first == 2 || first == -2) { 10 | second = 2; 11 | } 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElse.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void method() { 7 | if (first == 1) { 8 | second = 1; 9 | } else { 10 | if(first == 2 || first == -2) { 11 | second = 2; 12 | } 13 | } 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseBoolean.after.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | private boolean bool = false; 6 | 7 | public void method() { 8 | if (first == 1) { 9 | second = 1; 10 | } else if (!bool) { 11 | second = 2; 12 | } 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseBoolean.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | private boolean bool = false; 6 | 7 | public void method() { 8 | if (first == 1) { 9 | second = 1; 10 | } else { 11 | if(!bool) { 12 | second = 2; 13 | } 14 | } 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseMethod.after.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void method() { 7 | if (first == 1) { 8 | second = 1; 9 | } else if ("".equals("")) { 10 | second = 2; 11 | } 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseMethod.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void method() { 7 | if (first == 1) { 8 | second = 1; 9 | } else { 10 | if("".equals("")) { 11 | second = 2; 12 | } 13 | } 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertDoubleElseComparator.after.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 1; 5 | 6 | public void method() { 7 | if (first == 77 || 92 == first) { 8 | second = 1; 9 | } else { 10 | second = 2; 11 | } 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertDoubleElseComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 1; 5 | 6 | public void method() { 7 | if (first != 77 && 92 != first) { 8 | second = 2; 9 | } else { 10 | second = 1; 11 | } 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertMethodElseComparator.after.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 1; 5 | 6 | public void method() { 7 | if (success()) { 8 | second = 1; 9 | } else { 10 | second = 2; 11 | } 12 | } 13 | 14 | private boolean success() { 15 | return true; 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertMethodElseComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 1; 5 | 6 | public void method() { 7 | if (!success()) { 8 | second = 2; 9 | } else { 10 | second = 1; 11 | } 12 | } 13 | 14 | private boolean success() { 15 | return true; 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertRangeElseComparator.after.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 1; 5 | 6 | public void method() { 7 | if (first >= 30 && first < 35) { 8 | second = 1; 9 | } else { 10 | second = 2; 11 | } 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertRangeElseComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 1; 5 | 6 | public void method() { 7 | if (first < 30 || first >= 35) { 8 | second = 2; 9 | } else { 10 | second = 1; 11 | } 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertSingleElseComparator.after.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 1; 5 | 6 | public void method() { 7 | if (1 == first) { 8 | second = 1; 9 | } else { 10 | second = 2; 11 | } 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertSingleElseComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 1; 5 | 6 | public void method() { 7 | if (1 != first) { 8 | second = 2; 9 | } else { 10 | second = 1; 11 | } 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/EqualsBitwiseComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void positive() { 7 | boolean result = (first ^ 0xffffffff) == 32768; 8 | } 9 | 10 | public void regular() { 11 | boolean result = (first ^ 0xffffffff) == -32768; 12 | } 13 | 14 | public void flipped() { 15 | boolean result = -32768 == (first ^ 0xffffffff); 16 | } 17 | 18 | public void inverted() { 19 | boolean result = -32768 == (0xffffffff ^ first); 20 | } 21 | 22 | public void complimented() { 23 | boolean result = ~first == -32768; 24 | } 25 | 26 | public void prefix() { 27 | boolean result = (--first ^ 0xffffffff) == -32768; 28 | } 29 | 30 | public void suffix() { 31 | boolean result = (first++ ^ 0xffffffff) == -32768; 32 | } 33 | 34 | public void parenthesised() { 35 | boolean result = ((first * 4) ^ 0xffffffff) == -32768; 36 | } 37 | 38 | public void variable() { 39 | boolean result = (first ^ 0xffffffff) == ~second; 40 | } 41 | 42 | public void obstructions() { 43 | boolean result = ((first << 6) / 2 ^ 0xffffffff) == (0xffffffff ^ second - 4); 44 | } 45 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/GreaterThanBitwiseComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void positive() { 7 | boolean result = (first ^ 0xffffffff) > 32768; 8 | } 9 | 10 | public void regular() { 11 | boolean result = (first ^ 0xffffffff) > -32768; 12 | } 13 | 14 | public void flipped() { 15 | boolean result = -32768 > (first ^ 0xffffffff); 16 | } 17 | 18 | public void inverted() { 19 | boolean result = -32768 > (0xffffffff ^ first); 20 | } 21 | 22 | public void complimented() { 23 | boolean result = ~first > -32768; 24 | } 25 | 26 | public void prefix() { 27 | boolean result = (--first ^ 0xffffffff) > -32768; 28 | } 29 | 30 | public void suffix() { 31 | boolean result = (first++ ^ 0xffffffff) > -32768; 32 | } 33 | 34 | public void parenthesised() { 35 | boolean result = ((first * 4) ^ 0xffffffff) > -32768; 36 | } 37 | 38 | public void variable() { 39 | boolean result = (first ^ 0xffffffff) > ~second; 40 | } 41 | 42 | public void obstructions() { 43 | boolean result = ((first << 6) / 2 ^ 0xffffffff) > (0xffffffff ^ second - 4); 44 | } 45 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/GreaterThanEqualBitwiseComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void positive() { 7 | boolean result = (first ^ 0xffffffff) >= 32768; 8 | } 9 | 10 | public void regular() { 11 | boolean result = (first ^ 0xffffffff) >= -32768; 12 | } 13 | 14 | public void flipped() { 15 | boolean result = -32768 >= (first ^ 0xffffffff); 16 | } 17 | 18 | public void inverted() { 19 | boolean result = -32768 >= (0xffffffff ^ first); 20 | } 21 | 22 | public void complimented() { 23 | boolean result = ~first >= -32768; 24 | } 25 | 26 | public void prefix() { 27 | boolean result = (--first ^ 0xffffffff) >= -32768; 28 | } 29 | 30 | public void suffix() { 31 | boolean result = (first++ ^ 0xffffffff) >= -32768; 32 | } 33 | 34 | public void parenthesised() { 35 | boolean result = ((first * 4) ^ 0xffffffff) >= -32768; 36 | } 37 | 38 | public void variable() { 39 | boolean result = (first ^ 0xffffffff) >= ~second; 40 | } 41 | 42 | public void obstructions() { 43 | boolean result = ((first << 6) / 2 ^ 0xffffffff) >= (0xffffffff ^ second - 4); 44 | } 45 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/IgnoredComparators.java: -------------------------------------------------------------------------------- 1 | class IgnoredComparators { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void bitwiseNegative() { 7 | boolean result = -(first ^ 0xffffffff) == -2; 8 | } 9 | 10 | public void bitwiseOr() { 11 | boolean result = (first | 1 ^ 0xffffffff) == -1; 12 | } 13 | 14 | public void bitwiseOrReversed() { 15 | boolean result = (1 | first ^ 0xffffffff) == -1; 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/LessThanBitwiseComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void positive() { 7 | boolean result = (first ^ 0xffffffff) < 32768; 8 | } 9 | 10 | public void regular() { 11 | boolean result = (first ^ 0xffffffff) < -32768; 12 | } 13 | 14 | public void flipped() { 15 | boolean result = -32768 < (first ^ 0xffffffff); 16 | } 17 | 18 | public void inverted() { 19 | boolean result = -32768 < (0xffffffff ^ first); 20 | } 21 | 22 | public void complimented() { 23 | boolean result = ~first < -32768; 24 | } 25 | 26 | public void prefix() { 27 | boolean result = (--first ^ 0xffffffff) < -32768; 28 | } 29 | 30 | public void suffix() { 31 | boolean result = (first++ ^ 0xffffffff) < -32768; 32 | } 33 | 34 | public void parenthesised() { 35 | boolean result = ((first * 4) ^ 0xffffffff) < -32768; 36 | } 37 | 38 | public void variable() { 39 | boolean result = (first ^ 0xffffffff) < ~second; 40 | } 41 | 42 | public void obstructions() { 43 | boolean result = ((first << 6) / 2 ^ 0xffffffff) < (0xffffffff ^ second - 4); 44 | } 45 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/LessThanEqualBitwiseComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void positive() { 7 | boolean result = (first ^ 0xffffffff) <= 32768; 8 | } 9 | 10 | public void regular() { 11 | boolean result = (first ^ 0xffffffff) <= -32768; 12 | } 13 | 14 | public void flipped() { 15 | boolean result = -32768 <= (first ^ 0xffffffff); 16 | } 17 | 18 | public void inverted() { 19 | boolean result = -32768 <= (0xffffffff ^ first); 20 | } 21 | 22 | public void complimented() { 23 | boolean result = ~first <= -32768; 24 | } 25 | 26 | public void prefix() { 27 | boolean result = (--first ^ 0xffffffff) <= -32768; 28 | } 29 | 30 | public void suffix() { 31 | boolean result = (first++ ^ 0xffffffff) <= -32768; 32 | } 33 | 34 | public void parenthesised() { 35 | boolean result = ((first * 4) ^ 0xffffffff) <= -32768; 36 | } 37 | 38 | public void variable() { 39 | boolean result = (first ^ 0xffffffff) <= ~second; 40 | } 41 | 42 | public void obstructions() { 43 | boolean result = ((first << 6) / 2 ^ 0xffffffff) <= (0xffffffff ^ second - 4); 44 | } 45 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/NotEqualsBitwiseComparator.java: -------------------------------------------------------------------------------- 1 | class Comparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void positive() { 7 | boolean result = (first ^ 0xffffffff) != 32768; 8 | } 9 | 10 | public void regular() { 11 | boolean result = (first ^ 0xffffffff) != -32768; 12 | } 13 | 14 | public void flipped() { 15 | boolean result = -32768 != (first ^ 0xffffffff); 16 | } 17 | 18 | public void inverted() { 19 | boolean result = -32768 != (0xffffffff ^ first); 20 | } 21 | 22 | public void complimented() { 23 | boolean result = ~first != -32768; 24 | } 25 | 26 | public void prefix() { 27 | boolean result = (--first ^ 0xffffffff) != -32768; 28 | } 29 | 30 | public void suffix() { 31 | boolean result = (first++ ^ 0xffffffff) != -32768; 32 | } 33 | 34 | public void parenthesised() { 35 | boolean result = ((first * 4) ^ 0xffffffff) != -32768; 36 | } 37 | 38 | public void variable() { 39 | boolean result = (first ^ 0xffffffff) != ~second; 40 | } 41 | 42 | public void obstructions() { 43 | boolean result = ((first << 6) / 2 ^ 0xffffffff) != (0xffffffff ^ second - 4); 44 | } 45 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/PointlessBitwiseComparator.java: -------------------------------------------------------------------------------- 1 | class PointlessBitwiseComparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void bitwiseLessThanNegative() { 7 | boolean result = (first ^ 0xffffffff) < -32768; 8 | } 9 | 10 | public void bitwiseLessThanPositive() { 11 | boolean result = (first ^ 0xffffffff) < 32768; 12 | } 13 | 14 | public void bitwiseLessThanReversed() { 15 | boolean result = -32768 < (first ^ 0xffffffff); 16 | } 17 | 18 | public void bitwiseLessThanOperandReversed() { 19 | boolean result = -32768 < (0xffffffff ^ first); 20 | } 21 | 22 | public void bitwiseLessThanBitwise() { 23 | boolean result = (first ^ 0xffffffff) < (0xffffffff ^ second); 24 | } 25 | 26 | public void bitwiseEquals() { 27 | boolean result = (first ^ 0xffffffff) == -1; 28 | } 29 | 30 | public void bitwiseNotEquals() { 31 | boolean result = (0xffffffff ^ first) != -1; 32 | } 33 | 34 | public void bitwiseGreaterThan() { 35 | boolean result = (first ^ 0xffffffff) > -1; 36 | } 37 | 38 | public void bitwiseGreaterThanReversed() { 39 | boolean result = -1 > (first ^ 0xffffffff); 40 | } 41 | 42 | public void bitwiseLessThanEqual() { 43 | boolean result = -1 <= (first ^ 0xffffffff); 44 | } 45 | 46 | public void bitwiseGreaterThanEqual() { 47 | boolean result = (first ^ 0xffffffff) >= -221; 48 | } 49 | 50 | public void bitwiseNot() { 51 | boolean result = !((first ^ 0xffffffff) == -2); 52 | } 53 | 54 | public void bitwiseAnd() { 55 | boolean result = (first & 0xff ^ 0xffffffff) == -1; 56 | } 57 | 58 | public void bitwiseAndReversed() { 59 | boolean result = (0xff & first ^ 0xffffffff) == -1; 60 | } 61 | 62 | public void bitwiseShiftLeft() { 63 | boolean result = (first << 16 ^ 0xffffffff) == -1; 64 | } 65 | 66 | public void bitwiseShiftLeftReversed() { 67 | boolean result = (16 << first ^ 0xffffffff) == -1; 68 | } 69 | 70 | public void bitwiseShiftRight() { 71 | boolean result = (first >> 16 ^ 0xffffffff) == -1; 72 | } 73 | 74 | public void bitwiseShiftRightReversed() { 75 | boolean result = (16 >> first ^ 0xffffffff) == -1; 76 | } 77 | 78 | public void bitwiseAdd() { 79 | boolean result = (first + 1 ^ 0xffffffff) == -1; 80 | } 81 | 82 | public void bitwiseAddReversed() { 83 | boolean result = (1 + first ^ 0xffffffff) == -1; 84 | } 85 | 86 | public void bitwiseSubtract() { 87 | boolean result = (first - 1 ^ 0xffffffff) == -1; 88 | } 89 | 90 | public void bitwiseSubtractReversed() { 91 | boolean result = (1 - first ^ 0xffffffff) == -1; 92 | } 93 | 94 | public void bitwiseMultiply() { 95 | boolean result = (first * 1 ^ 0xffffffff) == -1; 96 | } 97 | 98 | public void bitwiseMultiplyReversed() { 99 | boolean result = (1 * first ^ 0xffffffff) == -1; 100 | } 101 | 102 | public void bitwiseDivide() { 103 | boolean result = (first / 1 ^ 0xffffffff) == -1; 104 | } 105 | 106 | public void bitwiseDivideReversed() { 107 | boolean result = (1 / first ^ 0xffffffff) == -1; 108 | } 109 | 110 | public void bitwiseModulus() { 111 | boolean result = (first % 1 ^ 0xffffffff) == -1; 112 | } 113 | 114 | public void bitwiseModulusReversed() { 115 | boolean result = (1 % first ^ 0xffffffff) == -1; 116 | } 117 | 118 | public void bitwiseIncrement() { 119 | boolean result = (first++ ^ 0xffffffff) == -1; 120 | } 121 | 122 | public void bitwiseIncrementReversed() { 123 | boolean result = (++first ^ 0xffffffff) == -1; 124 | } 125 | 126 | public void bitwiseDecrement() { 127 | boolean result = (first-- ^ 0xffffffff) == -1; 128 | } 129 | 130 | public void bitwiseDecrementReversed() { 131 | boolean result = (--first ^ 0xffffffff) == -1; 132 | } 133 | 134 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/TildeComparator.java: -------------------------------------------------------------------------------- 1 | class PointlessBitwiseComparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void positive() { 7 | boolean result = ~first == 32768; 8 | } 9 | 10 | public void regular() { 11 | boolean result = ~first == -32768; 12 | } 13 | 14 | public void inverted() { 15 | boolean result = -32768 == (~first); 16 | } 17 | 18 | public void complimented() { 19 | boolean result = ~first == -32768; 20 | } 21 | 22 | public void prefix() { 23 | boolean result = ~(--first) == -32768; 24 | } 25 | 26 | public void suffix() { 27 | boolean result = ~(first++) == -32768; 28 | } 29 | 30 | public void parenthesised() { 31 | boolean result = ~(first * 4) == -32768; 32 | } 33 | 34 | public void variable() { 35 | boolean result = ~first == ~second; 36 | } 37 | 38 | public void obstructions() { 39 | boolean result = ~((first << 6) / 2) == (0xffffffff ^ second - 4); 40 | } 41 | 42 | public void tilde() { 43 | boolean result = ~first < -32768; 44 | } 45 | 46 | public void tildeParenthesised() { 47 | boolean result = ~(first) < -32768; 48 | } 49 | 50 | public void tildeAnd() { 51 | boolean result = ~(first & 0xff) == -1; 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/flow/inline_nested_else/NestedElse.java: -------------------------------------------------------------------------------- 1 | class NestedElse { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void simpleNest() { 7 | if (first == 1) { 8 | second = 1; 9 | } else { 10 | if(first == 2) { 11 | second = 2; 12 | } 13 | } 14 | } 15 | 16 | public void doubleNest() { 17 | if (first == 1) { 18 | second = 1; 19 | } else { 20 | if(first == 2) { 21 | second = 2; 22 | } else { 23 | if(first == 3) { 24 | second = 3; 25 | } else { 26 | second = 4; 27 | } 28 | } 29 | } 30 | } 31 | 32 | public void nestMultiStatementIgnored() { 33 | if (first == 1) { 34 | second = 1; 35 | } else { 36 | if(first == 2) { 37 | second = 2; 38 | } 39 | second = 4; 40 | } 41 | } 42 | 43 | public void singleIfNestIgnored() { 44 | if (first == 1) { 45 | if(first == 2) { 46 | second = 2; 47 | } 48 | } 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseBooleanComparator.java: -------------------------------------------------------------------------------- 1 | class InverseElseComparator { 2 | 3 | private int second = 2; 4 | private boolean bool = false; 5 | 6 | public void notBoolean() { 7 | if (!bool) { 8 | second = 1; 9 | } else { 10 | second = 2; 11 | } 12 | } 13 | 14 | public void booleanNestedInverse() { 15 | if (!(bool || bool)) { 16 | second = 1; 17 | } else { 18 | second = 2; 19 | } 20 | } 21 | 22 | public void booleanIgnored() { 23 | if (bool) { 24 | second = 1; 25 | } else { 26 | second = 2; 27 | } 28 | } 29 | 30 | public void doubleBooleanIgnored() { 31 | if (bool && bool) { 32 | second = 1; 33 | } else { 34 | second = 2; 35 | } 36 | } 37 | 38 | public void booleanLiteral() { 39 | if (bool != true) { 40 | second = 2; 41 | } else { 42 | second = 1; 43 | } 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseElseComparator.java: -------------------------------------------------------------------------------- 1 | class InverseElseComparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | private boolean bool = false; 6 | 7 | public void simpleInversion() { 8 | if (first != 1) { 9 | second = 1; 10 | } else { 11 | second = 2; 12 | } 13 | } 14 | 15 | public void simpleInversionReversed() { 16 | if (1 != first) { 17 | second = 1; 18 | } else { 19 | second = 2; 20 | } 21 | } 22 | 23 | public void doubleExpressionInversion() { 24 | if (first != 77 && first != 92) { 25 | second = 1; 26 | } else { 27 | second = 2; 28 | } 29 | } 30 | 31 | public void tripleExpression() { 32 | if (first != 77 && first != 92 && first != 15) { 33 | second = 1; 34 | } else { 35 | second = 2; 36 | } 37 | } 38 | 39 | public void mixedExpression() { 40 | if (bool != false && 15 != first && !bool) { 41 | second = 1; 42 | } else { 43 | second = 2; 44 | } 45 | } 46 | 47 | public void mixedDouble() { 48 | if (first != 65535 && !bool) { 49 | second = 1; 50 | } else { 51 | second = 2; 52 | } 53 | } 54 | 55 | public void doubleExpressionIgnored() { 56 | if (first == 106 || first == 118) { 57 | second = 1; 58 | } else { 59 | second = 2; 60 | } 61 | } 62 | 63 | public void elseIfIgnored() { 64 | if (first != 1) { 65 | second = 1; 66 | } else if(second != 1) { 67 | second = 2; 68 | } 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseMethodComparator.java: -------------------------------------------------------------------------------- 1 | class InverseElseComparator { 2 | 3 | private int second = 2; 4 | 5 | public void notEqualsString() { 6 | if (!method()) { 7 | second = 1; 8 | } else { 9 | second = 2; 10 | } 11 | } 12 | 13 | private boolean method() { 14 | return true; 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseRangeComparator.java: -------------------------------------------------------------------------------- 1 | class InverseElseComparator { 2 | 3 | private int first = 1; 4 | private int second = 2; 5 | 6 | public void rangeInversion() { 7 | if (first < 30 || first >= 35) { 8 | second = 1; 9 | } else { 10 | second = 2; 11 | } 12 | } 13 | 14 | public void rangeIgnored() { 15 | if (first >= 35 && first < 40) { 16 | second = 1; 17 | } else { 18 | second = 2; 19 | } 20 | } 21 | 22 | } --------------------------------------------------------------------------------