diff --git a/deobfuscation/build.gradle b/build.gradle
similarity index 62%
rename from deobfuscation/build.gradle
rename to build.gradle
index d867518..241aae4 100644
--- a/deobfuscation/build.gradle
+++ b/build.gradle
@@ -4,7 +4,7 @@ plugins {
}
group 'world.gregs.intellij.plugins'
-version '1.1.0'
+version '1.2.0'
repositories {
mavenCentral()
@@ -32,8 +32,12 @@ intellij {
}
patchPluginXml {
changeNotes """
- Inspections added:
- Inverse else comparator
- Inline nested else statments
+ Expanded inspection functionality:
+ Tilde support fo r'pointless bitwise comparator'
+ Negative boolean and method support for 'inverse else comparator'
+ Multi-operand support for 'inverse else comparator'
+
+ Added additional highlighting tests
+ Added fix tests
"""
}
\ No newline at end of file
diff --git a/deobfuscation/settings.gradle b/deobfuscation/settings.gradle
deleted file mode 100644
index a4cfe45..0000000
--- a/deobfuscation/settings.gradle
+++ /dev/null
@@ -1,2 +0,0 @@
-rootProject.name = 'deobfuscation'
-
diff --git a/deobfuscation/src/main/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspection.kt b/deobfuscation/src/main/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspection.kt
deleted file mode 100644
index 3060b6b..0000000
--- a/deobfuscation/src/main/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspection.kt
+++ /dev/null
@@ -1,188 +0,0 @@
-package world.gregs.intellij.plugins.bitwise
-
-import com.intellij.codeInspection.ProblemDescriptor
-import com.intellij.openapi.project.Project
-import com.intellij.psi.*
-import com.intellij.psi.JavaTokenType.*
-import com.intellij.psi.tree.IElementType
-import com.intellij.psi.util.PsiUtil
-import com.intellij.psi.util.PsiUtilCore
-import com.intellij.util.containers.ContainerUtil
-import com.siyeh.ig.BaseInspection
-import com.siyeh.ig.BaseInspectionVisitor
-import com.siyeh.ig.InspectionGadgetsFix
-import com.siyeh.ig.psiutils.CommentTracker
-import com.siyeh.ig.psiutils.JavaPsiMathUtil
-import org.jetbrains.annotations.NonNls
-import world.gregs.intellij.plugins.DeobfuscateToolBundle
-import world.gregs.intellij.plugins.DeobfuscateUtil.isNumber
-
-class PointlessBitwiseComparatorInspection : BaseInspection() {
-
- override fun getDisplayName(): String {
- return DeobfuscateToolBundle.message("pointless.bitwise.comparator.display.name")
- }
-
- public override fun buildErrorString(vararg infos: Any): String {
- val expression = infos[0] as PsiExpression
- val replacementExpression = calculateReplacementExpression(expression)
- return DeobfuscateToolBundle.message("expression.can.be.replaced.problem.descriptor", replacementExpression)
- }
-
- override fun isEnabledByDefault(): Boolean {
- return true
- }
-
- @NonNls
- internal fun calculateReplacementExpression(expression: PsiExpression): String {
- if (expression !is PsiBinaryExpression) {
- return ""
- }
- val tokenType = expression.operationTokenType
- val left = expression.lOperand
- val right = expression.rOperand ?: return ""
-
- if(isBitwiseOperator(left) && isBitwiseOperator(right)) {
- val lOperand = getBitwiseOperandText(left)
- val rOperand = getBitwiseOperandText(right)
- if(lOperand != null && rOperand != null) {
- return "$rOperand ${getToken(tokenType)} $lOperand"
- }
- } else if(isBitwiseOperator(left) && isNumber(right) || isNumber(left) && isBitwiseOperator(right)) {
- val flip = isNumber(left) && isBitwiseOperator(right)
- val number = JavaPsiMathUtil.getNumberFromLiteral(if(flip) left else right)
- val operand = getBitwiseOperandText(if(flip) right else left)
- if(number != null && operand != null) {
- val inverseToken = when(tokenType) {
- GT -> LT
- GE -> LE
- LT -> GT
- LE -> GE
- else -> tokenType
- }
- return "$operand ${getToken(if(flip) tokenType else inverseToken)} ${decrementReverseValue(number)}"
- }
- } else {
- throw IllegalStateException("Didn't expect to see you here.")
- }
- return ""
- }
-
- override fun buildVisitor(): BaseInspectionVisitor {
- return PointlessBitwiseVisitor()
- }
-
- public override fun buildFix(vararg infos: Any): InspectionGadgetsFix? {
- return PointlessBitwiseFix()
- }
-
- private inner class PointlessBitwiseFix : InspectionGadgetsFix() {
-
- override fun getFamilyName(): String {
- return DeobfuscateToolBundle.message("pointless.bitwise.comparator.simplify.quickfix")
- }
-
- public override fun doFix(project: Project, descriptor: ProblemDescriptor) {
- val expression = descriptor.psiElement as PsiExpression
- val ct = CommentTracker()
- val newExpression = calculateReplacementExpression(expression)
- if (!newExpression.isEmpty()) {
- ct.replaceAndRestoreComments(expression, newExpression)
- }
- }
- }
-
- private inner class PointlessBitwiseVisitor : BaseInspectionVisitor() {
-
- override fun visitPolyadicExpression(expression: PsiPolyadicExpression) {
- super.visitPolyadicExpression(expression)
- val sign = expression.operationTokenType
-
- if (!comparisonTokens.contains(sign)) {
- return
- }
-
- if (PsiUtilCore.hasErrorElementChild(expression)) {
- return
- }
-
- val operands = expression.operands
- val parenthesized = operands.filterIsInstance()
- val bitwise = parenthesized.any { isBitwiseOperator(it.expression) }
-
- if(!bitwise) {
- return
- }
-
- val bitwiseCount = parenthesized.count { isBitwiseOperator(it.expression) }
- if(bitwiseCount != 2) {
- val number = operands.any { isNumber(it) }
-
- if (!number) {
- return
- }
- }
-
- registerError(expression, expression)
- }
- }
-
- companion object {
- internal val comparisonTokens = ContainerUtil.immutableSet(EQEQ, NE, LT, GT, LE, GE)
-
- private fun decrementReverseValue(number: Number): String {
- val decremented = -number.toLong() - 1
- return if (decremented > Int.MAX_VALUE || decremented < Int.MIN_VALUE) {
- "${decremented}L"
- } else {
- decremented.toString()
- }
- }
-
- private fun getToken(type: IElementType): String {
- return when(type) {
- GT -> ">"
- GE -> ">="
- LT -> "<"
- LE -> "<="
- EQEQ -> "=="
- NE -> "!="
- else -> ""
- }
- }
-
- private fun isHex(expression: PsiExpression?): Boolean {
- return expression != null && (expression.type == PsiType.INT && expression.text == "0xffffffff" || expression.type == PsiType.LONG && expression.text == "0xffffffffffffffffL")
- }
-
- private fun isBitwiseOperator(expression: PsiExpression?): Boolean {
- val express = PsiUtil.skipParenthesizedExprDown(expression) as? PsiBinaryExpression ?: return false
- val sign = express.operationTokenType
-
- if(sign != XOR) {
- return false
- }
-
- if(isHex(express.lOperand) || isHex(express.rOperand)) {
- return true
- }
-
- return false
- }
-
- private fun getBitwiseOperandText(expression: PsiExpression): String? {
- val express = PsiUtil.skipParenthesizedExprDown(expression) as? PsiBinaryExpression ?: return null
- val op = when {
- isHex(express.lOperand) -> express.rOperand
- isHex(express.rOperand) -> express.lOperand
- else -> null
- }
-
- return if(op is PsiPolyadicExpression && op.operationTokenType == AND) {
- "(${op.text})"
- } else {
- op?.text
- }
- }
- }
-}
\ No newline at end of file
diff --git a/deobfuscation/src/main/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspection.kt b/deobfuscation/src/main/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspection.kt
deleted file mode 100644
index 0f64d69..0000000
--- a/deobfuscation/src/main/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspection.kt
+++ /dev/null
@@ -1,155 +0,0 @@
-package world.gregs.intellij.plugins.flow
-
-import com.intellij.codeInspection.ProblemDescriptor
-import com.intellij.openapi.project.Project
-import com.intellij.psi.*
-import com.intellij.psi.JavaTokenType.*
-import com.intellij.util.containers.ContainerUtil
-import com.siyeh.ig.BaseInspection
-import com.siyeh.ig.BaseInspectionVisitor
-import com.siyeh.ig.InspectionGadgetsFix
-import com.siyeh.ig.PsiReplacementUtil
-import com.siyeh.ig.psiutils.CommentTracker
-import com.siyeh.ig.psiutils.ComparisonUtils
-import org.jetbrains.annotations.NonNls
-import world.gregs.intellij.plugins.DeobfuscateToolBundle
-import world.gregs.intellij.plugins.DeobfuscateUtil.isNumber
-
-class InverseElseComparatorInspection : BaseInspection() {
-
- override fun getDisplayName(): String {
- return DeobfuscateToolBundle.message("inverse.else.comparator.display.name")
- }
-
- public override fun buildErrorString(vararg infos: Any): String {
- val expression = infos[0] as PsiExpression
- val statement = infos[1] as PsiIfStatement
- val ct = CommentTracker()
- val replacement = calculateReplacementExpression(statement, ct)
- return DeobfuscateToolBundle.message(
- "comparator.can.be.inverted.problem.descriptor",
- ct.text(expression),
- replacement
- )
- }
-
- override fun isEnabledByDefault(): Boolean {
- return true
- }
-
- override fun buildVisitor(): BaseInspectionVisitor {
- return object : BaseInspectionVisitor() {
- override fun visitIfStatement(statement: PsiIfStatement) {
- super.visitIfStatement(statement)
-
- //Must have else block statement
- if(statement.elseBranch !is PsiBlockStatement) {
- return
- }
-
- val expression = statement.condition as? PsiBinaryExpression
- ?: return
-
- //Check expression has operands
- val left = expression.lOperand
- val right = expression.rOperand
- ?: return
-
- //Check format matches expected
- val sign = expression.operationTokenType
- val invalid = when (sign) {
- //Variable doesn't equal number or visa versa
- NE -> left is PsiReferenceExpression && !isNumber(right) || isNumber(left) && right !is PsiReferenceExpression
- //Both operands are binary expressions that have a range operation type
- OROR -> left !is PsiBinaryExpression || right !is PsiBinaryExpression || !comparisonTokens.contains(left.operationTokenType) || !comparisonTokens.contains(right.operationTokenType)
- //Both operands are binary expressions that both have a not-equal operators
- ANDAND -> left !is PsiBinaryExpression || right !is PsiBinaryExpression || left.operationTokenType != NE || right.operationTokenType != NE
- else -> true
- }
-
- //If format invalid; ignore
- if (invalid) {
- return
- }
-
- registerError(statement, expression, statement)
- }
- }
- }
-
- public override fun buildFix(vararg infos: Any): InspectionGadgetsFix? {
- return object : InspectionGadgetsFix() {
-
- override fun getFamilyName(): String {
- return DeobfuscateToolBundle.message("inverse.else.comparator.invert.quickfix")
- }
-
- public override fun doFix(project: Project, descriptor: ProblemDescriptor) {
- val statement = descriptor.psiElement as PsiIfStatement
-
- val expression = statement.condition as? PsiBinaryExpression
- ?: return
-
- val ct = CommentTracker()
-
- //Replace expression with negative comparator
- val expected = calculateReplacementExpression(statement, ct)
- PsiReplacementUtil.replaceExpression(expression, expected, ct)
-
- //Switch branches
- val branch = statement.thenBranch
- val elseBranch = statement.elseBranch?.copy() as? PsiStatement
- if(branch != null) {
- statement.setElseBranch(branch)
- }
- if(elseBranch != null) {
- statement.setThenBranch(elseBranch)
- }
- }
- }
- }
-
- @NonNls
- internal fun calculateReplacementExpression(statement: PsiIfStatement, ct: CommentTracker): String {
- val expression = statement.condition as? PsiBinaryExpression
- ?: return ""
-
- val sign = expression.operationTokenType
- return when (sign) {
- NE -> replaceOperation(expression, ComparisonUtils.getNegatedComparison(sign), ct)
- OROR, ANDAND -> {
- //Get operands as expressions
- val left = expression.lOperand as? PsiBinaryExpression
- ?: return ""
- val right = expression.rOperand as? PsiBinaryExpression
- ?: return ""
- //Replace expressions with negated operators
- val leftNew = replaceOperation(left, ComparisonUtils.getNegatedComparison(left.operationTokenType), ct)
- val rightNew = replaceOperation(right, ComparisonUtils.getNegatedComparison(right.operationTokenType), ct)
- //Change statement operator
- val opposite = when (sign) {
- OROR -> "&&"
- ANDAND -> "||"
- else -> throw IllegalStateException()
- }
- "$leftNew $opposite $rightNew"
- }
- else -> ""
- }
- }
-
- /**
- * Replaces [expression] operator
- * @param expression The binary expression who's operator to replace
- * @param operator The new operator
- * @param ct CommentTracker
- * @return [expression] as a string with the new [operator]
- */
- private fun replaceOperation(expression: PsiBinaryExpression, operator: String, ct: CommentTracker): String {
- return "${ct.text(expression.lOperand)} $operator ${ct.text(expression.rOperand!!)}"
- }
-
- companion object {
- internal val comparisonTokens = ContainerUtil.immutableSet(LT, GT, LE, GE)
- }
-}
\ No newline at end of file
diff --git a/deobfuscation/src/test/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspectionTest.kt b/deobfuscation/src/test/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspectionTest.kt
deleted file mode 100644
index 0ac58e3..0000000
--- a/deobfuscation/src/test/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspectionTest.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package world.gregs.intellij.plugins.bitwise
-
-import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
-
-
-internal class PointlessBitwiseComparatorInspectionTest : LightCodeInsightFixtureTestCase() {
- companion object {
- private const val fileName = "inspection.java"
- }
-
- override fun getTestDataPath(): String {
- val path = PointlessBitwiseComparatorInspectionTest::class.java.getResource(fileName).path
- return path.substring(0, path.length - fileName.length)
- }
-
- fun testPointlessBitwiseComparator() {
- myFixture.enableInspections(PointlessBitwiseComparatorInspection::class.java)
- myFixture.testHighlighting(true, false, false, fileName)
- }
-}
\ No newline at end of file
diff --git a/deobfuscation/src/test/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspectionTest.kt b/deobfuscation/src/test/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspectionTest.kt
deleted file mode 100644
index e659969..0000000
--- a/deobfuscation/src/test/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspectionTest.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package world.gregs.intellij.plugins.flow
-
-import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
-
-internal class InlineNestedElseInspectionTest : LightCodeInsightFixtureTestCase() {
- companion object {
- private const val fileName = "NestedElse.java"
- }
-
- override fun getTestDataPath(): String {
- val path = InlineNestedElseInspectionTest::class.java.getResource(fileName).path
- return path.substring(0, path.length - fileName.length)
- }
-
- fun testNestedElse() {
- myFixture.enableInspections(InlineNestedElseInspection::class.java)
- myFixture.testHighlighting(true, false, false, fileName)
- }
-}
\ No newline at end of file
diff --git a/deobfuscation/src/test/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspectionTest.kt b/deobfuscation/src/test/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspectionTest.kt
deleted file mode 100644
index 01f49a6..0000000
--- a/deobfuscation/src/test/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspectionTest.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package world.gregs.intellij.plugins.flow
-
-import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
-
-internal class InverseElseComparatorInspectionTest : LightCodeInsightFixtureTestCase() {
- companion object {
- private const val fileName = "InverseElseComparator.java"
- }
-
- override fun getTestDataPath(): String {
- val path = InverseElseComparatorInspectionTest::class.java.getResource(fileName).path
- return path.substring(0, path.length - fileName.length)
- }
-
- fun testInverseElseComparator() {
- myFixture.enableInspections(InverseElseComparatorInspection::class.java)
- myFixture.testHighlighting(true, false, false, fileName)
- }
-}
\ No newline at end of file
diff --git a/deobfuscation/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
similarity index 100%
rename from deobfuscation/gradle/wrapper/gradle-wrapper.jar
rename to gradle/wrapper/gradle-wrapper.jar
diff --git a/deobfuscation/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
similarity index 100%
rename from deobfuscation/gradle/wrapper/gradle-wrapper.properties
rename to gradle/wrapper/gradle-wrapper.properties
diff --git a/deobfuscation/gradlew b/gradlew
similarity index 100%
rename from deobfuscation/gradlew
rename to gradlew
diff --git a/deobfuscation/gradlew.bat b/gradlew.bat
similarity index 100%
rename from deobfuscation/gradlew.bat
rename to gradlew.bat
diff --git a/intellij-plugins.iml b/intellij-plugins.iml
deleted file mode 100644
index 93bf3fa..0000000
--- a/intellij-plugins.iml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..2164fb4
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'intellij-deobfuscation-plugin'
+
diff --git a/deobfuscation/src/inspectionDescriptions/InlineNestedElse.html b/src/inspectionDescriptions/InlineNestedElse.html
similarity index 100%
rename from deobfuscation/src/inspectionDescriptions/InlineNestedElse.html
rename to src/inspectionDescriptions/InlineNestedElse.html
diff --git a/deobfuscation/src/inspectionDescriptions/InverseElseComparator.html b/src/inspectionDescriptions/InverseElseComparator.html
similarity index 100%
rename from deobfuscation/src/inspectionDescriptions/InverseElseComparator.html
rename to src/inspectionDescriptions/InverseElseComparator.html
diff --git a/deobfuscation/src/inspectionDescriptions/PointlessBitwiseComparator.html b/src/inspectionDescriptions/PointlessBitwiseComparator.html
similarity index 100%
rename from deobfuscation/src/inspectionDescriptions/PointlessBitwiseComparator.html
rename to src/inspectionDescriptions/PointlessBitwiseComparator.html
diff --git a/deobfuscation/src/main/kotlin/world/gregs/intellij/plugins/DeobfuscateToolBundle.kt b/src/main/kotlin/world/gregs/intellij/plugins/DeobfuscateToolBundle.kt
similarity index 100%
rename from deobfuscation/src/main/kotlin/world/gregs/intellij/plugins/DeobfuscateToolBundle.kt
rename to src/main/kotlin/world/gregs/intellij/plugins/DeobfuscateToolBundle.kt
diff --git a/deobfuscation/src/main/kotlin/world/gregs/intellij/plugins/DeobfuscateUtil.kt b/src/main/kotlin/world/gregs/intellij/plugins/DeobfuscateUtil.kt
similarity index 100%
rename from deobfuscation/src/main/kotlin/world/gregs/intellij/plugins/DeobfuscateUtil.kt
rename to src/main/kotlin/world/gregs/intellij/plugins/DeobfuscateUtil.kt
diff --git a/src/main/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspection.kt b/src/main/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspection.kt
new file mode 100644
index 0000000..75536a7
--- /dev/null
+++ b/src/main/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspection.kt
@@ -0,0 +1,195 @@
+package world.gregs.intellij.plugins.bitwise
+
+import com.intellij.codeInspection.ProblemDescriptor
+import com.intellij.openapi.project.Project
+import com.intellij.psi.*
+import com.intellij.psi.JavaTokenType.*
+import com.intellij.psi.util.PsiUtil
+import com.intellij.psi.util.PsiUtilCore
+import com.intellij.util.containers.ContainerUtil
+import com.siyeh.ig.BaseInspection
+import com.siyeh.ig.BaseInspectionVisitor
+import com.siyeh.ig.InspectionGadgetsFix
+import com.siyeh.ig.psiutils.CommentTracker
+import com.siyeh.ig.psiutils.ComparisonUtils
+import com.siyeh.ig.psiutils.JavaPsiMathUtil
+import org.jetbrains.annotations.NonNls
+import world.gregs.intellij.plugins.DeobfuscateToolBundle
+import world.gregs.intellij.plugins.DeobfuscateUtil.isNumber
+
+class PointlessBitwiseComparatorInspection : BaseInspection() {
+
+ override fun getDisplayName(): String {
+ return DeobfuscateToolBundle.message("pointless.bitwise.comparator.display.name")
+ }
+
+ public override fun buildErrorString(vararg infos: Any): String {
+ val expression = infos[0] as PsiExpression
+ val replacementExpression = calculateReplacementExpression(expression)
+ return DeobfuscateToolBundle.message("expression.can.be.replaced.problem.descriptor", replacementExpression)
+ }
+
+ override fun isEnabledByDefault(): Boolean {
+ return true
+ }
+
+ @NonNls
+ internal fun calculateReplacementExpression(expression: PsiExpression): String {
+ if (expression !is PsiBinaryExpression) {
+ return ""
+ }
+ val operator = expression.operationSign
+ val left = expression.lOperand
+ val right = expression.rOperand ?: return ""
+
+ val ct = CommentTracker()
+
+ if (isBitwiseOperator(left) && isBitwiseOperator(right)) {
+ val lOperand = getOperandText(left, ct)
+ val rOperand = getOperandText(right, ct)
+ if (lOperand != null && rOperand != null) {
+ return "$rOperand ${ct.text(operator)} $lOperand"
+ }
+ } else if (isBitwiseOperator(left) && isNumber(right) || isNumber(left) && isBitwiseOperator(right)) {
+ val flip = isNumber(left) && isBitwiseOperator(right)
+ val number = JavaPsiMathUtil.getNumberFromLiteral(if (flip) left else right)
+ val operand = getOperandText(if (flip) right else left, ct)
+ if (number != null && operand != null) {
+ val flipped = when (operator.tokenType) {
+ GT, GE, LT, LE -> ComparisonUtils.getFlippedComparison(operator.tokenType)
+ else -> ct.text(operator)
+ }
+ return "$operand ${if (flip) ct.text(operator) else flipped} ${decrementReverseValue(number)}"
+ }
+ } else {
+ throw IllegalStateException("Didn't expect to see you here.")
+ }
+ return ""
+ }
+
+ override fun buildVisitor(): BaseInspectionVisitor {
+ return object : BaseInspectionVisitor() {
+
+ override fun visitPolyadicExpression(expression: PsiPolyadicExpression) {
+ super.visitPolyadicExpression(expression)
+ val sign = expression.operationTokenType
+
+ if (!comparisonTokens.contains(sign)) {
+ return
+ }
+
+ if (PsiUtilCore.hasErrorElementChild(expression)) {
+ return
+ }
+
+ val operands = expression.operands
+ val parenthesized = operands.filter { it is PsiParenthesizedExpression || it is PsiPrefixExpression }
+
+ //Must have at least one bitwise operator
+ val bitwise = parenthesized.any { isBitwiseOperator(it) }
+ if (!bitwise) {
+ return
+ }
+
+ //Either two bitwise or a bitwise and a number
+ val bitwiseCount = parenthesized.count { isBitwiseOperator(it) }
+ if (bitwiseCount != 2) {
+ val number = operands.any { isNumber(it) }
+
+ if (!number) {
+ return
+ }
+ }
+
+ registerError(expression, expression)
+ }
+ }
+ }
+
+ public override fun buildFix(vararg infos: Any): InspectionGadgetsFix? {
+ return object : InspectionGadgetsFix() {
+
+ override fun getFamilyName(): String {
+ return DeobfuscateToolBundle.message("pointless.bitwise.comparator.simplify.quickfix")
+ }
+
+ public override fun doFix(project: Project, descriptor: ProblemDescriptor) {
+ val expression = descriptor.psiElement as PsiExpression
+ val ct = CommentTracker()
+ val newExpression = calculateReplacementExpression(expression)
+ if (!newExpression.isEmpty()) {
+ ct.replaceAndRestoreComments(expression, newExpression)
+ }
+ }
+ }
+ }
+
+ companion object {
+ internal val comparisonTokens = ContainerUtil.immutableSet(EQEQ, NE, LT, GT, LE, GE)
+
+ private fun decrementReverseValue(number: Number): String {
+ val decremented = -number.toLong() - 1
+ return if (decremented > Int.MAX_VALUE || decremented < Int.MIN_VALUE) {
+ "${decremented}L"
+ } else {
+ decremented.toString()
+ }
+ }
+
+ private fun isHex(expression: PsiExpression?): Boolean {
+ return expression != null && (expression.type == PsiType.INT && expression.text == "0xffffffff" || expression.type == PsiType.LONG && expression.text == "0xffffffffffffffffL")
+ }
+
+ private fun isBitwiseOperator(express: PsiExpression?): Boolean {
+ val expression = if (express is PsiParenthesizedExpression) PsiUtil.skipParenthesizedExprDown(express) else express
+ when (expression) {
+ is PsiPrefixExpression -> {
+ if (expression.operationTokenType == TILDE) {
+ return true
+ }
+ }
+ is PsiBinaryExpression -> {
+ val sign = expression.operationTokenType
+
+ if (sign != XOR) {
+ return false
+ }
+
+ if (isHex(expression.lOperand) || isHex(expression.rOperand)) {
+ return true
+ }
+ }
+ }
+ return false
+ }
+
+ private fun getOperandText(expression: PsiExpression, ct: CommentTracker): String? {
+ val express = PsiUtil.skipParenthesizedExprDown(expression) ?: return null
+ val operand: PsiExpression? = when (express) {
+ is PsiPrefixExpression -> {
+ var child = express.lastChild as? PsiExpression
+ if (child is PsiParenthesizedExpression) {
+ child = PsiUtil.skipParenthesizedExprDown(child)
+ }
+ PsiUtil.skipParenthesizedExprDown(child) ?: return null
+ }
+ is PsiBinaryExpression -> {
+ when {
+ isHex(express.lOperand) -> express.rOperand
+ isHex(express.rOperand) -> express.lOperand
+ else -> null
+ }
+ }
+ else -> null
+ }
+ //AND operators still require parentheses
+ return if (operand is PsiPolyadicExpression && operand.operationTokenType == AND) {
+ "(${ct.text(operand)})"
+ } else if (operand != null) {
+ ct.text(operand)
+ } else {
+ null
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/deobfuscation/src/main/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspection.kt b/src/main/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspection.kt
similarity index 96%
rename from deobfuscation/src/main/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspection.kt
rename to src/main/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspection.kt
index fa00a6a..29896c2 100644
--- a/deobfuscation/src/main/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspection.kt
+++ b/src/main/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspection.kt
@@ -35,7 +35,7 @@ class InlineNestedElseInspection : SingleStatementInBlockInspection() {
override fun isApplicable(body: PsiStatement?): Boolean {
//If body is else branch of parent
val parent = body?.parent
- if(body is PsiBlockStatement && parent is PsiIfStatement && parent.elseBranch == body) {
+ if (body is PsiBlockStatement && parent is PsiIfStatement && parent.elseBranch == body) {
val codeBlock = body.codeBlock
if (PsiUtilCore.hasErrorElementChild(codeBlock)) {
return false
@@ -85,11 +85,11 @@ class InlineNestedElseInspection : SingleStatementInBlockInspection() {
override fun doFix(project: Project, descriptor: ProblemDescriptor) {
var statement = PsiTreeUtil.getNonStrictParentOfType(descriptor.startElement, PsiStatement::class.java)
- ?: return
+ ?: return
if (statement is PsiBlockStatement) {
statement = PsiTreeUtil.getNonStrictParentOfType(statement.parent, PsiStatement::class.java)
- ?: return
+ ?: return
}
val body = when (statement) {
diff --git a/src/main/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspection.kt b/src/main/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspection.kt
new file mode 100644
index 0000000..30a5b68
--- /dev/null
+++ b/src/main/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspection.kt
@@ -0,0 +1,215 @@
+package world.gregs.intellij.plugins.flow
+
+import com.intellij.codeInspection.ProblemDescriptor
+import com.intellij.openapi.project.Project
+import com.intellij.psi.*
+import com.intellij.psi.JavaTokenType.*
+import com.intellij.psi.util.PsiUtil
+import com.intellij.util.containers.ContainerUtil
+import com.siyeh.ig.BaseInspection
+import com.siyeh.ig.BaseInspectionVisitor
+import com.siyeh.ig.InspectionGadgetsFix
+import com.siyeh.ig.PsiReplacementUtil
+import com.siyeh.ig.psiutils.CommentTracker
+import com.siyeh.ig.psiutils.ComparisonUtils
+import org.jetbrains.annotations.NonNls
+import world.gregs.intellij.plugins.DeobfuscateToolBundle
+
+class InverseElseComparatorInspection : BaseInspection() {
+
+ override fun getDisplayName(): String {
+ return DeobfuscateToolBundle.message("inverse.else.comparator.display.name")
+ }
+
+ public override fun buildErrorString(vararg infos: Any): String {
+ val expression = infos[0] as PsiExpression
+ val statement = infos[1] as PsiIfStatement
+ val ct = CommentTracker()
+ val replacement = calculateReplacementExpression(statement, ct)
+ return DeobfuscateToolBundle.message(
+ "comparator.can.be.inverted.problem.descriptor",
+ ct.text(expression),
+ replacement
+ )
+ }
+
+ override fun isEnabledByDefault(): Boolean {
+ return true
+ }
+
+ override fun buildVisitor(): BaseInspectionVisitor {
+ return object : BaseInspectionVisitor() {
+ override fun visitIfStatement(statement: PsiIfStatement) {
+ super.visitIfStatement(statement)
+
+ //Must have else block statement
+ if (statement.elseBranch !is PsiBlockStatement) {
+ return
+ }
+
+ val expression = statement.condition
+ when (expression) {
+ is PsiPrefixExpression -> {
+ val child = expression.lastChild
+ //Check is exclamation boolean
+ if (expression.operationTokenType != EXCL || (child !is PsiReferenceExpression && child !is PsiParenthesizedExpression && child !is PsiMethodCallExpression)) {
+ return
+ }
+ }
+ is PsiPolyadicExpression -> {
+ //If binary do single & range check
+ if (expression is PsiBinaryExpression) {
+ //Check expression has operands
+ val left = expression.lOperand
+ val right = expression.rOperand
+ ?: return
+
+ //Check both operands are binary expressions that have a range operation type
+ val sign = expression.operationTokenType
+ val valid = when (sign) {
+ //Single operand
+ NE -> true
+ //Both operands are binary expressions that have a range operation type
+ OROR -> left is PsiBinaryExpression && right is PsiBinaryExpression && comparisonTokens.contains(left.operationTokenType) && comparisonTokens.contains(right.operationTokenType)
+ else -> false
+ }
+
+ if (valid) {
+ registerError(statement, expression, statement)
+ return
+ }
+ }
+
+ //Check all operands are joined by '&&' and are negative
+ expression.operands.forEach {
+ val token = expression.getTokenBeforeOperand(it)?.tokenType
+ if (token == null || token == ANDAND) {
+ //Only continue if negated
+ if (it is PsiPrefixExpression && it.operationTokenType == EXCL) {
+ return@forEach
+ } else if (it is PsiBinaryExpression && it.operationTokenType == NE) {
+ return@forEach
+ }
+ }
+ return
+ }
+ }
+ else -> return
+ }
+ registerError(statement, expression, statement)
+ }
+ }
+ }
+
+ public override fun buildFix(vararg infos: Any): InspectionGadgetsFix? {
+ return object : InspectionGadgetsFix() {
+
+ override fun getFamilyName(): String {
+ return DeobfuscateToolBundle.message("inverse.else.comparator.invert.quickfix")
+ }
+
+ public override fun doFix(project: Project, descriptor: ProblemDescriptor) {
+ val statement = descriptor.psiElement as PsiIfStatement
+
+ val expression = statement.condition
+ if (expression is PsiPrefixExpression || expression is PsiBinaryExpression) {
+ val ct = CommentTracker()
+
+ //Replace expression with negative comparator
+ val expected = calculateReplacementExpression(statement, ct)
+ if (expected.isEmpty()) {
+ throw IllegalStateException("Empty replacement for $statement $expression")
+ } else {
+ PsiReplacementUtil.replaceExpression(expression, expected, ct)
+ }
+
+ //Switch branches
+ val branch = statement.thenBranch
+ val elseBranch = statement.elseBranch?.copy() as? PsiStatement
+ if (branch != null) {
+ statement.setElseBranch(branch)
+ }
+ if (elseBranch != null) {
+ statement.setThenBranch(elseBranch)
+ }
+ }
+ return
+ }
+ }
+ }
+
+ @NonNls
+ internal fun calculateReplacementExpression(statement: PsiIfStatement, ct: CommentTracker): String {
+ val expression = statement.condition
+ return when (expression) {
+ is PsiPrefixExpression -> {
+ var child = expression.lastChild
+ if (child is PsiParenthesizedExpression) {
+ child = PsiUtil.deparenthesizeExpression(child)
+ }
+ ct.text(child)
+ }
+ is PsiPolyadicExpression -> {
+ //If binary check single & range
+ if (expression is PsiBinaryExpression) {
+ val sign = expression.operationTokenType
+ when (sign) {
+ NE -> return replaceOperation(expression, ComparisonUtils.getNegatedComparison(sign), ct)
+ OROR -> {
+ //Get operands as expressions
+ val left = expression.lOperand as? PsiBinaryExpression
+ ?: return ""
+ val right = expression.rOperand as? PsiBinaryExpression
+ ?: return ""
+ //Replace expressions with negated operators
+ val leftNew = replaceOperation(left, ComparisonUtils.getNegatedComparison(left.operationTokenType), ct)
+ val rightNew = replaceOperation(right, ComparisonUtils.getNegatedComparison(right.operationTokenType), ct)
+ //Change statement operator
+ val opposite = when (sign) {
+ OROR -> "&&"
+ ANDAND -> "||"
+ else -> throw IllegalStateException()
+ }
+ return "$leftNew $opposite $rightNew"
+ }
+ }
+ }
+ val builder = StringBuilder()
+ //Apply each operand, negating operators and removing negative prefixes
+ expression.operands.forEach {
+ //Apply logical operators
+ val token = expression.getTokenBeforeOperand(it)
+ if (token != null) {
+ builder.append(" || ")
+ }
+
+ //Apply operands
+ if (it is PsiPrefixExpression) {
+ //Ignore prefix
+ builder.append(ct.text(it.lastChild))
+ } else if (it is PsiBinaryExpression) {
+ //Negate relational operators
+ builder.append(replaceOperation(it, ComparisonUtils.getNegatedComparison(it.operationTokenType), ct))
+ }
+ }
+ builder.toString()
+ }
+ else -> ""
+ }
+ }
+
+ /**
+ * Replaces [expression] operator
+ * @param expression The binary expression who's operator to replace
+ * @param operator The new operator
+ * @param ct CommentTracker
+ * @return [expression] as a string with the new [operator]
+ */
+ private fun replaceOperation(expression: PsiBinaryExpression, operator: String, ct: CommentTracker): String {
+ return "${ct.text(expression.lOperand)} $operator ${ct.text(expression.rOperand!!)}"
+ }
+
+ companion object {
+ internal val comparisonTokens = ContainerUtil.immutableSet(LT, GT, LE, GE)
+ }
+}
\ No newline at end of file
diff --git a/deobfuscation/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml
similarity index 100%
rename from deobfuscation/src/main/resources/META-INF/plugin.xml
rename to src/main/resources/META-INF/plugin.xml
diff --git a/deobfuscation/src/main/resources/world/gregs/intellij/plugins/DeobfuscateToolBundle.properties b/src/main/resources/world/gregs/intellij/plugins/DeobfuscateToolBundle.properties
similarity index 100%
rename from deobfuscation/src/main/resources/world/gregs/intellij/plugins/DeobfuscateToolBundle.properties
rename to src/main/resources/world/gregs/intellij/plugins/DeobfuscateToolBundle.properties
diff --git a/src/test/kotlin/world/gregs/intellij/plugins/LightInspectionTester.kt b/src/test/kotlin/world/gregs/intellij/plugins/LightInspectionTester.kt
new file mode 100644
index 0000000..18ebd7a
--- /dev/null
+++ b/src/test/kotlin/world/gregs/intellij/plugins/LightInspectionTester.kt
@@ -0,0 +1,104 @@
+package world.gregs.intellij.plugins
+
+import com.intellij.codeHighlighting.HighlightDisplayLevel
+import com.intellij.codeInsight.daemon.HighlightDisplayKey
+import com.intellij.profile.codeInspection.ProjectInspectionProfileManager
+import com.intellij.testFramework.UsefulTestCase
+import com.siyeh.ig.LightInspectionTestCase
+import org.intellij.lang.annotations.Language
+import org.junit.Assert
+
+/**
+ * Clone of [LightInspectionTestCase]
+ * @author Bas Leijdekkers
+ */
+abstract class LightInspectionTester : LightTester(false) {
+
+ @Throws(Exception::class)
+ override fun setUp() {
+ super.setUp()
+
+ val inspection = getInspection()
+ if (inspection != null) {
+ val project = myFixture.project
+ val displayKey = HighlightDisplayKey.find(inspection.shortName)
+ val currentProfile = ProjectInspectionProfileManager.getInstance(project).currentProfile
+ val errorLevel = currentProfile.getErrorLevel(displayKey, null)
+ if (errorLevel === HighlightDisplayLevel.DO_NOT_SHOW) {
+ currentProfile.setErrorLevel(displayKey, HighlightDisplayLevel.WARNING, project)
+ }
+ }
+ }
+
+ protected fun addEnvironmentClass(@Language("JAVA") classText: String) {
+ myFixture.addClass(classText)
+ }
+
+ protected fun doStatementTest(@Language(value = "JAVA", prefix = "@SuppressWarnings(\"all\") class X { void m() {", suffix = "}}") statementText: String) {
+ doTest("class X { void m() {$statementText}}")
+ }
+
+ protected fun doMemberTest(@Language(value = "JAVA", prefix = "@SuppressWarnings(\"all\") class X {", suffix = "}") memberText: String) {
+ doTest("class X {$memberText}")
+ }
+
+ protected fun doTest(@Language("JAVA") classText: String) {
+ doTest(classText, "X.java")
+ }
+
+ protected fun assertQuickFixNotAvailable(name: String) {
+ UsefulTestCase.assertEmpty(myFixture.filterAvailableIntentions(name))
+ }
+
+ protected fun checkQuickFix(name: String, @Language("JAVA") result: String) {
+ val intention = myFixture.getAvailableIntention(name)
+ Assert.assertNotNull(intention)
+ myFixture.launchAction(intention!!)
+ myFixture.checkResult(result)
+ }
+
+ protected fun checkQuickFix(intentionName: String) {
+ val intention = myFixture.getAvailableIntention(intentionName)
+ Assert.assertNotNull(intention)
+ myFixture.launchAction(intention!!)
+ myFixture.checkResultByFile(getTestName(false) + ".after.java")
+ }
+
+ protected fun doTest(@Language("JAVA") classText: String, fileName: String) {
+ val newText = StringBuilder()
+ var start = 0
+ var end = classText.indexOf("/*")
+ while (end >= 0) {
+ newText.append(classText, start, end)
+ start = end + 2
+ end = classText.indexOf("*/", end)
+ if (end < 0) {
+ throw IllegalArgumentException("invalid class text")
+ }
+ val text = classText.substring(start, end)
+ when {
+ text.isEmpty() -> newText.append("")
+ "!" == text -> newText.append("")
+ "_" == text -> newText.append("")
+ text.startsWith("!") -> newText.append("")
+ text.startsWith(" ") -> newText.append("/*").append(text).append("*/")
+ else -> newText.append("")
+ }
+ start = end + 2
+ end = classText.indexOf("/*", end + 1)
+ }
+ newText.append(classText, start, classText.length)
+ myFixture.configureByText(fileName, newText.toString())
+ myFixture.testHighlighting(true, false, false)
+ }
+
+ protected fun doTest() {
+ doNamedTest(getTestName(false))
+ }
+
+ protected fun doNamedTest(name: String) {
+ myFixture.configureByFile("$name.java")
+ myFixture.testHighlighting(true, false, false)
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/kotlin/world/gregs/intellij/plugins/LightQuickFixTester.kt b/src/test/kotlin/world/gregs/intellij/plugins/LightQuickFixTester.kt
new file mode 100644
index 0000000..d4d5bd2
--- /dev/null
+++ b/src/test/kotlin/world/gregs/intellij/plugins/LightQuickFixTester.kt
@@ -0,0 +1,98 @@
+package world.gregs.intellij.plugins
+
+import com.intellij.ide.highlighter.JavaFileType
+import com.intellij.pom.java.LanguageLevel
+import com.intellij.testFramework.UsefulTestCase
+import com.intellij.testFramework.builders.JavaModuleFixtureBuilder
+import org.intellij.lang.annotations.Language
+import org.jetbrains.annotations.NonNls
+import org.junit.Assert
+import java.nio.file.FileSystems
+
+/**
+ * Clone of [com.siyeh.ig.IGQuickFixesTestCase]
+ * @author anna
+ */
+abstract class LightQuickFixTester : LightTester(true) {
+ abstract val myDefaultHint: String
+
+ @Throws(Exception::class)
+ override fun tuneFixture(builder: JavaModuleFixtureBuilder<*>?) {
+ builder!!.setLanguageLevel(LanguageLevel.JDK_1_8)
+ }
+
+ override fun getTestDataPath(): String {
+ return "${FileSystems.getDefault().getPath("").toAbsolutePath()}/src/test/resources/fixes/$basePath"
+ }
+
+ protected fun assertQuickfixNotAvailable() {
+ assertQuickfixNotAvailable(myDefaultHint)
+ }
+
+ protected fun assertQuickfixNotAvailable(quickfixName: String?) {
+ val testName = getTestName(false)
+ myFixture.configureByFile("$testName.java")
+ UsefulTestCase.assertEmpty("Quickfix \'$quickfixName\' is available but should not",
+ myFixture.filterAvailableIntentions(quickfixName!!))
+ }
+
+ protected fun assertQuickfixNotAvailable(quickfixName: String, @Language("JAVA") @NonNls text: String) {
+ var text = text
+ text = text.replace("/**/", "")
+ myFixture.configureByText(JavaFileType.INSTANCE, text)
+ UsefulTestCase.assertEmpty("Quickfix \'$quickfixName\' is available but should not",
+ myFixture.filterAvailableIntentions(quickfixName))
+ }
+
+ protected fun doTest() {
+ val testName = getTestName(false)
+ doTest(testName, myDefaultHint)
+ }
+
+ protected fun doTest(hint: String) {
+ val testName = getTestName(false)
+ doTest(testName, hint)
+ }
+
+ protected fun doTest(testName: String, hint: String) {
+ myFixture.configureByFile("$testName.java")
+ val action = myFixture.getAvailableIntention(hint)
+ Assert.assertNotNull(action)
+ myFixture.launchAction(action!!)
+ myFixture.checkResultByFile("$testName.after.java")
+ }
+
+ protected fun doExpressionTest(
+ hint: String,
+ @Language(value = "JAVA", prefix = "/** @noinspection ALL*/class \$X$ {static {System.out.print(", suffix = ");}}") @NonNls before: String,
+ @Language(value = "JAVA", prefix = "class \$X$ {static {System.out.print(", suffix = ");}}") @NonNls after: String) {
+ doTest(hint, "class \$X$ {static {System.out.print($before);}}", "class \$X$ {static {System.out.print($after);}}")
+ }
+
+ protected fun doMemberTest(
+ hint: String,
+ @Language(value = "JAVA", prefix = "/** @noinspection ALL*/class \$X$ {", suffix = "}") @NonNls before: String,
+ @Language(value = "JAVA", prefix = "class \$X$ {", suffix = "}") @NonNls after: String) {
+ doTest(hint, "class \$X$ {$before}", "class \$X$ {$after}")
+ }
+
+ protected fun doTest(hint: String,
+ @Language("JAVA") @NonNls before: String,
+ @Language("JAVA") @NonNls after: String) {
+ doTest(hint, before, after, "aaa.java")
+ }
+
+ protected fun doTest(hint: String,
+ @Language("JAVA") @NonNls before: String,
+ @Language("JAVA") @NonNls after: String,
+ fileName: String) {
+ var before = before
+ before = before.replace("/**/", "")
+ myFixture.configureByText(fileName, before)
+ val intention = myFixture.getAvailableIntention(hint)
+ Assert.assertNotNull(intention)
+ myFixture.launchAction(intention!!)
+ myFixture.checkResult(after)
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/kotlin/world/gregs/intellij/plugins/LightTester.kt b/src/test/kotlin/world/gregs/intellij/plugins/LightTester.kt
new file mode 100644
index 0000000..15e0762
--- /dev/null
+++ b/src/test/kotlin/world/gregs/intellij/plugins/LightTester.kt
@@ -0,0 +1,69 @@
+package world.gregs.intellij.plugins
+
+import com.intellij.codeInspection.InspectionProfileEntry
+import com.intellij.openapi.util.text.StringUtil
+import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase
+import com.siyeh.ig.BaseInspection
+import org.junit.Assert
+import java.nio.file.FileSystems
+
+abstract class LightTester(private val fix: Boolean) : JavaCodeInsightFixtureTestCase() {
+
+ @Throws(Exception::class)
+ override fun setUp() {
+ super.setUp()
+
+ val inspections = getInspections()
+ if (inspections != null) {
+ myFixture.enableInspections(*inspections)
+ }
+ }
+
+ private fun getInspections(): Array? {
+ val inspection = getInspection()
+ return inspection?.let { arrayOf(it) }
+ }
+
+ abstract fun getInspection(): BaseInspection?
+
+ override fun getTestDataPath(): String {
+ return "${FileSystems.getDefault().getPath("").toAbsolutePath()}/src/test/resources/${if (fix) "fixes" else "test"}/$basePath"
+ }
+
+ override fun getBasePath(): String {
+ val className = getInspectionClass().name
+ val words = className.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
+ val basePath = StringBuilder()
+ val lastWordIndex = words.size - 1
+ for (i in 0 until lastWordIndex) {
+ basePath.append(words[i]).append('/')
+ }
+ var lastWord = words[lastWordIndex]
+ lastWord = StringUtil.trimEnd(lastWord, "Inspection")
+ val length = lastWord.length
+ var upperCase = false
+ for (i in 0 until length) {
+ val ch = lastWord[i]
+ if (Character.isUpperCase(ch)) {
+ if (!upperCase) {
+ upperCase = true
+ if (i != 0) {
+ basePath.append('_')
+ }
+ }
+ basePath.append(Character.toLowerCase(ch))
+ } else {
+ upperCase = false
+ basePath.append(ch)
+ }
+ }
+ return basePath.toString()
+ }
+
+ protected fun getInspectionClass(): Class {
+ val inspection = getInspection()
+ Assert.assertNotNull("File-based tests should either return an inspection or override this method", inspection)
+ return inspection!!.javaClass
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorFixTest.kt b/src/test/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorFixTest.kt
new file mode 100644
index 0000000..5d43f2b
--- /dev/null
+++ b/src/test/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorFixTest.kt
@@ -0,0 +1,35 @@
+package world.gregs.intellij.plugins.bitwise
+
+import com.siyeh.ig.BaseInspection
+import world.gregs.intellij.plugins.DeobfuscateToolBundle
+import world.gregs.intellij.plugins.LightQuickFixTester
+
+internal class PointlessBitwiseComparatorFixTest : LightQuickFixTester() {
+
+ override val myDefaultHint = DeobfuscateToolBundle.message("pointless.bitwise.comparator.simplify.quickfix")
+
+ fun testRemoveBitwiseAndComparator() {
+ doTest()
+ }
+
+ fun testRemoveBitwiseComparator() {
+ doTest()
+ }
+
+ fun testRemoveComplimentAndComparator() {
+ doTest()
+ }
+
+ fun testRemoveComplimentComparator() {
+ doTest()
+ }
+
+ fun testRemoveFlippedBitwiseComparator() {
+ doTest()
+ }
+
+ override fun getInspection(): BaseInspection? {
+ return PointlessBitwiseComparatorInspection()
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspectionTest.kt b/src/test/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspectionTest.kt
new file mode 100644
index 0000000..ba62294
--- /dev/null
+++ b/src/test/kotlin/world/gregs/intellij/plugins/bitwise/PointlessBitwiseComparatorInspectionTest.kt
@@ -0,0 +1,47 @@
+package world.gregs.intellij.plugins.bitwise
+
+import com.siyeh.ig.BaseInspection
+import world.gregs.intellij.plugins.LightInspectionTester
+
+internal class PointlessBitwiseComparatorInspectionTest : LightInspectionTester() {
+
+ fun testPointlessBitwiseComparator() {
+ doTest()
+ }
+
+ fun testTildeComparator() {
+ doTest()
+ }
+
+ fun testIgnoredComparators() {
+ doTest()
+ }
+
+ fun testLessThanBitwiseComparator() {
+ doTest()
+ }
+
+ fun testLessThanEqualBitwiseComparator() {
+ doTest()
+ }
+
+ fun testGreaterThanBitwiseComparator() {
+ doTest()
+ }
+
+ fun testGreaterThanEqualBitwiseComparator() {
+ doTest()
+ }
+
+ fun testEqualsBitwiseComparator() {
+ doTest()
+ }
+
+ fun testNotEqualsBitwiseComparator() {
+ doTest()
+ }
+
+ override fun getInspection(): BaseInspection? {
+ return PointlessBitwiseComparatorInspection()
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseFixTest.kt b/src/test/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseFixTest.kt
new file mode 100644
index 0000000..c62bf22
--- /dev/null
+++ b/src/test/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseFixTest.kt
@@ -0,0 +1,25 @@
+package world.gregs.intellij.plugins.flow
+
+import com.siyeh.ig.BaseInspection
+import world.gregs.intellij.plugins.DeobfuscateToolBundle
+import world.gregs.intellij.plugins.LightQuickFixTester
+
+internal class InlineNestedElseFixTest : LightQuickFixTester() {
+ override val myDefaultHint = DeobfuscateToolBundle.message("inline.nested.else.quickfix")
+
+ fun testInlineNestedElse() {
+ doTest()
+ }
+
+ fun testInlineNestedElseBoolean() {
+ doTest()
+ }
+
+ fun testInlineNestedElseMethod() {
+ doTest()
+ }
+
+ override fun getInspection(): BaseInspection? {
+ return InlineNestedElseInspection()
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspectionTest.kt b/src/test/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspectionTest.kt
new file mode 100644
index 0000000..6b8fbb5
--- /dev/null
+++ b/src/test/kotlin/world/gregs/intellij/plugins/flow/InlineNestedElseInspectionTest.kt
@@ -0,0 +1,15 @@
+package world.gregs.intellij.plugins.flow
+
+import com.siyeh.ig.BaseInspection
+import world.gregs.intellij.plugins.LightInspectionTester
+
+internal class InlineNestedElseInspectionTest : LightInspectionTester() {
+
+ fun testNestedElse() {
+ doTest()
+ }
+
+ override fun getInspection(): BaseInspection? {
+ return InlineNestedElseInspection()
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorFixTest.kt b/src/test/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorFixTest.kt
new file mode 100644
index 0000000..0cc178d
--- /dev/null
+++ b/src/test/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorFixTest.kt
@@ -0,0 +1,29 @@
+package world.gregs.intellij.plugins.flow
+
+import com.siyeh.ig.BaseInspection
+import world.gregs.intellij.plugins.DeobfuscateToolBundle
+import world.gregs.intellij.plugins.LightQuickFixTester
+
+internal class InverseElseComparatorFixTest : LightQuickFixTester() {
+ override val myDefaultHint = DeobfuscateToolBundle.message("inverse.else.comparator.invert.quickfix")
+
+ fun testInvertSingleElseComparator() {
+ doTest()
+ }
+
+ fun testInvertDoubleElseComparator() {
+ doTest()
+ }
+
+ fun testInvertMethodElseComparator() {
+ doTest()
+ }
+
+ fun testInvertRangeElseComparator() {
+ doTest()
+ }
+
+ override fun getInspection(): BaseInspection? {
+ return InverseElseComparatorInspection()
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspectionTest.kt b/src/test/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspectionTest.kt
new file mode 100644
index 0000000..c2311c2
--- /dev/null
+++ b/src/test/kotlin/world/gregs/intellij/plugins/flow/InverseElseComparatorInspectionTest.kt
@@ -0,0 +1,27 @@
+package world.gregs.intellij.plugins.flow
+
+import com.siyeh.ig.BaseInspection
+import world.gregs.intellij.plugins.LightInspectionTester
+
+internal class InverseElseComparatorInspectionTest : LightInspectionTester() {
+
+ fun testInverseElseComparator() {
+ doTest()
+ }
+
+ fun testInverseBooleanComparator() {
+ doTest()
+ }
+
+ fun testInverseMethodComparator() {
+ doTest()
+ }
+
+ fun testInverseRangeComparator() {
+ doTest()
+ }
+
+ override fun getInspection(): BaseInspection? {
+ return InverseElseComparatorInspection()
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseAndComparator.after.java b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseAndComparator.after.java
new file mode 100644
index 0000000..63831bf
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseAndComparator.after.java
@@ -0,0 +1,9 @@
+class Comparator {
+
+ private int first = 1;
+
+ public void method() {
+ boolean result = (0x400 & first) == 0;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseAndComparator.java b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseAndComparator.java
new file mode 100644
index 0000000..22c141f
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseAndComparator.java
@@ -0,0 +1,9 @@
+class Comparator {
+
+ private int first = 1;
+
+ public void method() {
+ boolean result = (0x400 & first ^ 0xffffffff) == -1;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseComparator.after.java b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseComparator.after.java
new file mode 100644
index 0000000..a1d8267
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseComparator.after.java
@@ -0,0 +1,9 @@
+class Comparator {
+
+ private int first = 1;
+
+ public void method() {
+ boolean result = first > 32767;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseComparator.java b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseComparator.java
new file mode 100644
index 0000000..97bced8
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveBitwiseComparator.java
@@ -0,0 +1,9 @@
+class Comparator {
+
+ private int first = 1;
+
+ public void method() {
+ boolean result = (first ^ 0xffffffff) < -32768;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentAndComparator.after.java b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentAndComparator.after.java
new file mode 100644
index 0000000..daa3514
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentAndComparator.after.java
@@ -0,0 +1,9 @@
+class Comparator {
+
+ private int first = 1;
+
+ public void method() {
+ boolean result = (first & 0x400) == 0;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentAndComparator.java b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentAndComparator.java
new file mode 100644
index 0000000..ed1e9cb
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentAndComparator.java
@@ -0,0 +1,9 @@
+class Comparator {
+
+ private int first = 1;
+
+ public void method() {
+ boolean result = ~(first & 0x400) == -1;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentComparator.after.java b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentComparator.after.java
new file mode 100644
index 0000000..193e142
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentComparator.after.java
@@ -0,0 +1,11 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+ private int[] is = new int[1];
+
+ public void method() {
+ boolean result = (first ^ 0xffffffff) > -36 && is[second - -1] != 0;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentComparator.java b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentComparator.java
new file mode 100644
index 0000000..00d2154
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveComplimentComparator.java
@@ -0,0 +1,11 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+ private int[] is = new int[1];
+
+ public void method() {
+ boolean result = (first ^ 0xffffffff) > -36 && ~is[second - -1] != -1;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveFlippedBitwiseComparator.after.java b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveFlippedBitwiseComparator.after.java
new file mode 100644
index 0000000..8ba883d
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveFlippedBitwiseComparator.after.java
@@ -0,0 +1,9 @@
+class Comparator {
+
+ private int first = 1;
+
+ public void method() {
+ boolean result = first + 4 <= 0;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveFlippedBitwiseComparator.java b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveFlippedBitwiseComparator.java
new file mode 100644
index 0000000..9da46df
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/RemoveFlippedBitwiseComparator.java
@@ -0,0 +1,9 @@
+class Comparator {
+
+ private int first = 1;
+
+ public void method() {
+ boolean result = -1 <= (0xffffffff ^ first + 4);
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElse.after.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElse.after.java
new file mode 100644
index 0000000..483e20c
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElse.after.java
@@ -0,0 +1,14 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+
+ public void method() {
+ if (first == 1) {
+ second = 1;
+ } else if (first == 2 || first == -2) {
+ second = 2;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElse.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElse.java
new file mode 100644
index 0000000..60b8043
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElse.java
@@ -0,0 +1,16 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+
+ public void method() {
+ if (first == 1) {
+ second = 1;
+ } else {
+ if(first == 2 || first == -2) {
+ second = 2;
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseBoolean.after.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseBoolean.after.java
new file mode 100644
index 0000000..0db94c2
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseBoolean.after.java
@@ -0,0 +1,15 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+ private boolean bool = false;
+
+ public void method() {
+ if (first == 1) {
+ second = 1;
+ } else if (!bool) {
+ second = 2;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseBoolean.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseBoolean.java
new file mode 100644
index 0000000..762be88
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseBoolean.java
@@ -0,0 +1,17 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+ private boolean bool = false;
+
+ public void method() {
+ if (first == 1) {
+ second = 1;
+ } else {
+ if(!bool) {
+ second = 2;
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseMethod.after.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseMethod.after.java
new file mode 100644
index 0000000..6614b27
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseMethod.after.java
@@ -0,0 +1,14 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+
+ public void method() {
+ if (first == 1) {
+ second = 1;
+ } else if ("".equals("")) {
+ second = 2;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseMethod.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseMethod.java
new file mode 100644
index 0000000..6e63900
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inline_nested_else/InlineNestedElseMethod.java
@@ -0,0 +1,16 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+
+ public void method() {
+ if (first == 1) {
+ second = 1;
+ } else {
+ if("".equals("")) {
+ second = 2;
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertDoubleElseComparator.after.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertDoubleElseComparator.after.java
new file mode 100644
index 0000000..58ee749
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertDoubleElseComparator.after.java
@@ -0,0 +1,14 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 1;
+
+ public void method() {
+ if (first == 77 || 92 == first) {
+ second = 1;
+ } else {
+ second = 2;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertDoubleElseComparator.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertDoubleElseComparator.java
new file mode 100644
index 0000000..2ca0cce
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertDoubleElseComparator.java
@@ -0,0 +1,14 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 1;
+
+ public void method() {
+ if (first != 77 && 92 != first) {
+ second = 2;
+ } else {
+ second = 1;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertMethodElseComparator.after.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertMethodElseComparator.after.java
new file mode 100644
index 0000000..3ac9ed5
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertMethodElseComparator.after.java
@@ -0,0 +1,18 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 1;
+
+ public void method() {
+ if (success()) {
+ second = 1;
+ } else {
+ second = 2;
+ }
+ }
+
+ private boolean success() {
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertMethodElseComparator.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertMethodElseComparator.java
new file mode 100644
index 0000000..076ab2e
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertMethodElseComparator.java
@@ -0,0 +1,18 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 1;
+
+ public void method() {
+ if (!success()) {
+ second = 2;
+ } else {
+ second = 1;
+ }
+ }
+
+ private boolean success() {
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertRangeElseComparator.after.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertRangeElseComparator.after.java
new file mode 100644
index 0000000..75e8842
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertRangeElseComparator.after.java
@@ -0,0 +1,14 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 1;
+
+ public void method() {
+ if (first >= 30 && first < 35) {
+ second = 1;
+ } else {
+ second = 2;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertRangeElseComparator.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertRangeElseComparator.java
new file mode 100644
index 0000000..60cc05a
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertRangeElseComparator.java
@@ -0,0 +1,14 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 1;
+
+ public void method() {
+ if (first < 30 || first >= 35) {
+ second = 2;
+ } else {
+ second = 1;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertSingleElseComparator.after.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertSingleElseComparator.after.java
new file mode 100644
index 0000000..0e9bd34
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertSingleElseComparator.after.java
@@ -0,0 +1,14 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 1;
+
+ public void method() {
+ if (1 == first) {
+ second = 1;
+ } else {
+ second = 2;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertSingleElseComparator.java b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertSingleElseComparator.java
new file mode 100644
index 0000000..b116126
--- /dev/null
+++ b/src/test/resources/fixes/world/gregs/intellij/plugins/flow/inverse_else_comparator/InvertSingleElseComparator.java
@@ -0,0 +1,14 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 1;
+
+ public void method() {
+ if (1 != first) {
+ second = 2;
+ } else {
+ second = 1;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/EqualsBitwiseComparator.java b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/EqualsBitwiseComparator.java
new file mode 100644
index 0000000..4754a5e
--- /dev/null
+++ b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/EqualsBitwiseComparator.java
@@ -0,0 +1,45 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+
+ public void positive() {
+ boolean result = (first ^ 0xffffffff) == 32768;
+ }
+
+ public void regular() {
+ boolean result = (first ^ 0xffffffff) == -32768;
+ }
+
+ public void flipped() {
+ boolean result = -32768 == (first ^ 0xffffffff);
+ }
+
+ public void inverted() {
+ boolean result = -32768 == (0xffffffff ^ first);
+ }
+
+ public void complimented() {
+ boolean result = ~first == -32768;
+ }
+
+ public void prefix() {
+ boolean result = (--first ^ 0xffffffff) == -32768;
+ }
+
+ public void suffix() {
+ boolean result = (first++ ^ 0xffffffff) == -32768;
+ }
+
+ public void parenthesised() {
+ boolean result = ((first * 4) ^ 0xffffffff) == -32768;
+ }
+
+ public void variable() {
+ boolean result = (first ^ 0xffffffff) == ~second;
+ }
+
+ public void obstructions() {
+ boolean result = ((first << 6) / 2 ^ 0xffffffff) == (0xffffffff ^ second - 4);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/GreaterThanBitwiseComparator.java b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/GreaterThanBitwiseComparator.java
new file mode 100644
index 0000000..de9a657
--- /dev/null
+++ b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/GreaterThanBitwiseComparator.java
@@ -0,0 +1,45 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+
+ public void positive() {
+ boolean result = (first ^ 0xffffffff) > 32768;
+ }
+
+ public void regular() {
+ boolean result = (first ^ 0xffffffff) > -32768;
+ }
+
+ public void flipped() {
+ boolean result = -32768 > (first ^ 0xffffffff);
+ }
+
+ public void inverted() {
+ boolean result = -32768 > (0xffffffff ^ first);
+ }
+
+ public void complimented() {
+ boolean result = ~first > -32768;
+ }
+
+ public void prefix() {
+ boolean result = (--first ^ 0xffffffff) > -32768;
+ }
+
+ public void suffix() {
+ boolean result = (first++ ^ 0xffffffff) > -32768;
+ }
+
+ public void parenthesised() {
+ boolean result = ((first * 4) ^ 0xffffffff) > -32768;
+ }
+
+ public void variable() {
+ boolean result = (first ^ 0xffffffff) > ~second;
+ }
+
+ public void obstructions() {
+ boolean result = ((first << 6) / 2 ^ 0xffffffff) > (0xffffffff ^ second - 4);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/GreaterThanEqualBitwiseComparator.java b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/GreaterThanEqualBitwiseComparator.java
new file mode 100644
index 0000000..e485fa6
--- /dev/null
+++ b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/GreaterThanEqualBitwiseComparator.java
@@ -0,0 +1,45 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+
+ public void positive() {
+ boolean result = (first ^ 0xffffffff) >= 32768;
+ }
+
+ public void regular() {
+ boolean result = (first ^ 0xffffffff) >= -32768;
+ }
+
+ public void flipped() {
+ boolean result = -32768 >= (first ^ 0xffffffff);
+ }
+
+ public void inverted() {
+ boolean result = -32768 >= (0xffffffff ^ first);
+ }
+
+ public void complimented() {
+ boolean result = ~first >= -32768;
+ }
+
+ public void prefix() {
+ boolean result = (--first ^ 0xffffffff) >= -32768;
+ }
+
+ public void suffix() {
+ boolean result = (first++ ^ 0xffffffff) >= -32768;
+ }
+
+ public void parenthesised() {
+ boolean result = ((first * 4) ^ 0xffffffff) >= -32768;
+ }
+
+ public void variable() {
+ boolean result = (first ^ 0xffffffff) >= ~second;
+ }
+
+ public void obstructions() {
+ boolean result = ((first << 6) / 2 ^ 0xffffffff) >= (0xffffffff ^ second - 4);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/IgnoredComparators.java b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/IgnoredComparators.java
new file mode 100644
index 0000000..5bd4665
--- /dev/null
+++ b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/IgnoredComparators.java
@@ -0,0 +1,18 @@
+class IgnoredComparators {
+
+ private int first = 1;
+ private int second = 2;
+
+ public void bitwiseNegative() {
+ boolean result = -(first ^ 0xffffffff) == -2;
+ }
+
+ public void bitwiseOr() {
+ boolean result = (first | 1 ^ 0xffffffff) == -1;
+ }
+
+ public void bitwiseOrReversed() {
+ boolean result = (1 | first ^ 0xffffffff) == -1;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/LessThanBitwiseComparator.java b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/LessThanBitwiseComparator.java
new file mode 100644
index 0000000..c68b3dc
--- /dev/null
+++ b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/LessThanBitwiseComparator.java
@@ -0,0 +1,45 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+
+ public void positive() {
+ boolean result = (first ^ 0xffffffff) < 32768;
+ }
+
+ public void regular() {
+ boolean result = (first ^ 0xffffffff) < -32768;
+ }
+
+ public void flipped() {
+ boolean result = -32768 < (first ^ 0xffffffff);
+ }
+
+ public void inverted() {
+ boolean result = -32768 < (0xffffffff ^ first);
+ }
+
+ public void complimented() {
+ boolean result = ~first < -32768;
+ }
+
+ public void prefix() {
+ boolean result = (--first ^ 0xffffffff) < -32768;
+ }
+
+ public void suffix() {
+ boolean result = (first++ ^ 0xffffffff) < -32768;
+ }
+
+ public void parenthesised() {
+ boolean result = ((first * 4) ^ 0xffffffff) < -32768;
+ }
+
+ public void variable() {
+ boolean result = (first ^ 0xffffffff) < ~second;
+ }
+
+ public void obstructions() {
+ boolean result = ((first << 6) / 2 ^ 0xffffffff) < (0xffffffff ^ second - 4);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/LessThanEqualBitwiseComparator.java b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/LessThanEqualBitwiseComparator.java
new file mode 100644
index 0000000..9c5932c
--- /dev/null
+++ b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/LessThanEqualBitwiseComparator.java
@@ -0,0 +1,45 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+
+ public void positive() {
+ boolean result = (first ^ 0xffffffff) <= 32768;
+ }
+
+ public void regular() {
+ boolean result = (first ^ 0xffffffff) <= -32768;
+ }
+
+ public void flipped() {
+ boolean result = -32768 <= (first ^ 0xffffffff);
+ }
+
+ public void inverted() {
+ boolean result = -32768 <= (0xffffffff ^ first);
+ }
+
+ public void complimented() {
+ boolean result = ~first <= -32768;
+ }
+
+ public void prefix() {
+ boolean result = (--first ^ 0xffffffff) <= -32768;
+ }
+
+ public void suffix() {
+ boolean result = (first++ ^ 0xffffffff) <= -32768;
+ }
+
+ public void parenthesised() {
+ boolean result = ((first * 4) ^ 0xffffffff) <= -32768;
+ }
+
+ public void variable() {
+ boolean result = (first ^ 0xffffffff) <= ~second;
+ }
+
+ public void obstructions() {
+ boolean result = ((first << 6) / 2 ^ 0xffffffff) <= (0xffffffff ^ second - 4);
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/NotEqualsBitwiseComparator.java b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/NotEqualsBitwiseComparator.java
new file mode 100644
index 0000000..131fef9
--- /dev/null
+++ b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/NotEqualsBitwiseComparator.java
@@ -0,0 +1,45 @@
+class Comparator {
+
+ private int first = 1;
+ private int second = 2;
+
+ public void positive() {
+ boolean result = (first ^ 0xffffffff) != 32768;
+ }
+
+ public void regular() {
+ boolean result = (first ^ 0xffffffff) != -32768;
+ }
+
+ public void flipped() {
+ boolean result = -32768 != (first ^ 0xffffffff);
+ }
+
+ public void inverted() {
+ boolean result = -32768 != (0xffffffff ^ first);
+ }
+
+ public void complimented() {
+ boolean result = ~first != -32768;
+ }
+
+ public void prefix() {
+ boolean result = (--first ^ 0xffffffff) != -32768;
+ }
+
+ public void suffix() {
+ boolean result = (first++ ^ 0xffffffff) != -32768;
+ }
+
+ public void parenthesised() {
+ boolean result = ((first * 4) ^ 0xffffffff) != -32768;
+ }
+
+ public void variable() {
+ boolean result = (first ^ 0xffffffff) != ~second;
+ }
+
+ public void obstructions() {
+ boolean result = ((first << 6) / 2 ^ 0xffffffff) != (0xffffffff ^ second - 4);
+ }
+}
\ No newline at end of file
diff --git a/deobfuscation/src/test/resources/world/gregs/intellij/plugins/bitwise/inspection.java b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/PointlessBitwiseComparator.java
similarity index 87%
rename from deobfuscation/src/test/resources/world/gregs/intellij/plugins/bitwise/inspection.java
rename to src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/PointlessBitwiseComparator.java
index dfeca85..d058bc3 100644
--- a/deobfuscation/src/test/resources/world/gregs/intellij/plugins/bitwise/inspection.java
+++ b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/PointlessBitwiseComparator.java
@@ -47,18 +47,10 @@ public void bitwiseGreaterThanEqual() {
boolean result = (first ^ 0xffffffff) >= -221;
}
- public void bitwiseNegative() {
- boolean result = -(first ^ 0xffffffff) == -2;
- }
-
public void bitwiseNot() {
boolean result = !((first ^ 0xffffffff) == -2);
}
- public void bitwiseOnes() {
- boolean result = ~(first ^ 0xffffffff) == -2;
- }
-
public void bitwiseAnd() {
boolean result = (first & 0xff ^ 0xffffffff) == -1;
}
@@ -67,14 +59,6 @@ public void bitwiseAndReversed() {
boolean result = (0xff & first ^ 0xffffffff) == -1;
}
- public void bitwiseOr() {
- boolean result = (first | 1 ^ 0xffffffff) == -1;
- }
-
- public void bitwiseOrReversed() {
- boolean result = (1 | first ^ 0xffffffff) == -1;
- }
-
public void bitwiseShiftLeft() {
boolean result = (first << 16 ^ 0xffffffff) == -1;
}
@@ -147,12 +131,4 @@ public void bitwiseDecrementReversed() {
boolean result = (--first ^ 0xffffffff) == -1;
}
- public void bitwiseMultiple() {
- boolean result = (1 + first + second + 1 ^ 0xffffffff) == -1;
- }
-
- public void bitwiseMultipleBitwise() {
- boolean result = ((first << 6) / 2 ^ 0xffffffff) < (0xffffffff ^ second - 4);
- }
-
}
\ No newline at end of file
diff --git a/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/TildeComparator.java b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/TildeComparator.java
new file mode 100644
index 0000000..9ef6e7b
--- /dev/null
+++ b/src/test/resources/test/world/gregs/intellij/plugins/bitwise/pointless_bitwise_comparator/TildeComparator.java
@@ -0,0 +1,54 @@
+class PointlessBitwiseComparator {
+
+ private int first = 1;
+ private int second = 2;
+
+ public void positive() {
+ boolean result = ~first == 32768;
+ }
+
+ public void regular() {
+ boolean result = ~first == -32768;
+ }
+
+ public void inverted() {
+ boolean result = -32768 == (~first);
+ }
+
+ public void complimented() {
+ boolean result = ~first == -32768;
+ }
+
+ public void prefix() {
+ boolean result = ~(--first) == -32768;
+ }
+
+ public void suffix() {
+ boolean result = ~(first++) == -32768;
+ }
+
+ public void parenthesised() {
+ boolean result = ~(first * 4) == -32768;
+ }
+
+ public void variable() {
+ boolean result = ~first == ~second;
+ }
+
+ public void obstructions() {
+ boolean result = ~((first << 6) / 2) == (0xffffffff ^ second - 4);
+ }
+
+ public void tilde() {
+ boolean result = ~first < -32768;
+ }
+
+ public void tildeParenthesised() {
+ boolean result = ~(first) < -32768;
+ }
+
+ public void tildeAnd() {
+ boolean result = ~(first & 0xff) == -1;
+ }
+
+}
\ No newline at end of file
diff --git a/deobfuscation/src/test/resources/world/gregs/intellij/plugins/flow/NestedElse.java b/src/test/resources/test/world/gregs/intellij/plugins/flow/inline_nested_else/NestedElse.java
similarity index 100%
rename from deobfuscation/src/test/resources/world/gregs/intellij/plugins/flow/NestedElse.java
rename to src/test/resources/test/world/gregs/intellij/plugins/flow/inline_nested_else/NestedElse.java
diff --git a/src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseBooleanComparator.java b/src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseBooleanComparator.java
new file mode 100644
index 0000000..307a597
--- /dev/null
+++ b/src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseBooleanComparator.java
@@ -0,0 +1,46 @@
+class InverseElseComparator {
+
+ private int second = 2;
+ private boolean bool = false;
+
+ public void notBoolean() {
+ if (!bool) {
+ second = 1;
+ } else {
+ second = 2;
+ }
+ }
+
+ public void booleanNestedInverse() {
+ if (!(bool || bool)) {
+ second = 1;
+ } else {
+ second = 2;
+ }
+ }
+
+ public void booleanIgnored() {
+ if (bool) {
+ second = 1;
+ } else {
+ second = 2;
+ }
+ }
+
+ public void doubleBooleanIgnored() {
+ if (bool && bool) {
+ second = 1;
+ } else {
+ second = 2;
+ }
+ }
+
+ public void booleanLiteral() {
+ if (bool != true) {
+ second = 2;
+ } else {
+ second = 1;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/deobfuscation/src/test/resources/world/gregs/intellij/plugins/flow/InverseElseComparator.java b/src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseElseComparator.java
similarity index 64%
rename from deobfuscation/src/test/resources/world/gregs/intellij/plugins/flow/InverseElseComparator.java
rename to src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseElseComparator.java
index b501c06..c59a7b4 100644
--- a/deobfuscation/src/test/resources/world/gregs/intellij/plugins/flow/InverseElseComparator.java
+++ b/src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseElseComparator.java
@@ -2,6 +2,7 @@ class InverseElseComparator {
private int first = 1;
private int second = 2;
+ private boolean bool = false;
public void simpleInversion() {
if (first != 1) {
@@ -19,24 +20,32 @@ public void simpleInversionReversed() {
}
}
- public void rangeInversion() {
- if (first < 30 || first >= 35) {
+ public void doubleExpressionInversion() {
+ if (first != 77 && first != 92) {
second = 1;
} else {
second = 2;
}
}
- public void rangeIgnored() {
- if (first >= 35 && first < 40) {
+ public void tripleExpression() {
+ if (first != 77 && first != 92 && first != 15) {
second = 1;
} else {
second = 2;
- }
+ }
}
- public void doubleExpressionInversion() {
- if (first != 77 && first != 92) {
+ public void mixedExpression() {
+ if (bool != false && 15 != first && !bool) {
+ second = 1;
+ } else {
+ second = 2;
+ }
+ }
+
+ public void mixedDouble() {
+ if (first != 65535 && !bool) {
second = 1;
} else {
second = 2;
diff --git a/src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseMethodComparator.java b/src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseMethodComparator.java
new file mode 100644
index 0000000..36e8a14
--- /dev/null
+++ b/src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseMethodComparator.java
@@ -0,0 +1,17 @@
+class InverseElseComparator {
+
+ private int second = 2;
+
+ public void notEqualsString() {
+ if (!method()) {
+ second = 1;
+ } else {
+ second = 2;
+ }
+ }
+
+ private boolean method() {
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseRangeComparator.java b/src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseRangeComparator.java
new file mode 100644
index 0000000..6a013a3
--- /dev/null
+++ b/src/test/resources/test/world/gregs/intellij/plugins/flow/inverse_else_comparator/InverseRangeComparator.java
@@ -0,0 +1,22 @@
+class InverseElseComparator {
+
+ private int first = 1;
+ private int second = 2;
+
+ public void rangeInversion() {
+ if (first < 30 || first >= 35) {
+ second = 1;
+ } else {
+ second = 2;
+ }
+ }
+
+ public void rangeIgnored() {
+ if (first >= 35 && first < 40) {
+ second = 1;
+ } else {
+ second = 2;
+ }
+ }
+
+}
\ No newline at end of file