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