diff --git a/README.md b/README.md
index 3f8e7f14f..4bf66339d 100644
--- a/README.md
+++ b/README.md
@@ -34,28 +34,28 @@ Please see [Code Samples][docs:code-samples] topic on how to import and run code
In the following table, you may find all available samples provided in the separated directories as stand-alone projects available for running with the Gradle [`runIde`](tools_gradle_intellij_plugin.md#tasks-runide) task.
-| Code Sample | Description |
-|------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [Action Basics](./action_basics) | Action and Action Group patterns implementation, adds entries to the Tools menu. |
-| [Comparing References Inspection](./comparing_references_inspection) | Local Inspection Tool, adds entries to **Settings | Editor | Inspections | Java | Probable Bugs**. |
-| [Conditional Operator Intention](./conditional_operator_intention) | Intention action, suggests converting a ternary operator into an `if` block and adds entry to **Settings | Editor | Intentions | SDK Intentions**. |
-| [Editor Basics](./editor_basics) | Basic Editor APIs example with editor popup menu with extra actions. |
-| [Framework Basics](./framework_basics) | Basic *SDK Demo Framework* support added to the **File | New | Project | Java** wizard. |
-| [Kotlin Demo](./kotlin_demo) | Kotlin example extending the *Main Menu* with a **Greeting** menu group. |
-| [Live Templates](./live_templates) | Live templates for Markdown language, adds an entry to the **Settings | Editor | Live Templates** dialog. |
-| [Max Opened Projects](./max_opened_projects) | Application services and listeners, shows warning dialog when more than 3 open projects are opened. |
-| [Module](./module) | *SDK Demo Module* module type added to the **File | New | Project...** wizard. |
-| [Product Specific - PyCharm Sample](./product_specific/pycharm_basics) | Plugin project configuration for the PyCharm IDE. |
-| [Project Model](./project_model) | Interacts with the project model, adds menu items to **Tools** and **Editor Context** menus. |
-| [Project View Pane](./project_view_pane) | Project View Pane listing only image files. |
-| [Project Wizard](./project_wizard) | Project Wizard example with demo steps. |
-| [PSI Demo](./psi_demo) | PSI Navigation features presentation. |
-| [Run Configuration](./run_configuration) | Run configuration implementation with factory, options and UI. |
-| [Settings](./settings) | Custom settings panel, adds a settings panel to the **Settings** panel under **Tools**. |
-| [Simple Language Plugin](./simple_language_plugin) | Custom language support, defines a new *Simple language* with syntax highlighting, annotations, code completion, and other features. |
-| [Theme Basics](./theme_basics) | Sample *theme* plugin with basic interface modifications. |
-| [Tool Window](./tool_window) | Custom Tool Window example plugin. |
-| [Tree Structure Provider](./tree_structure_provider) | Tree Structure Provider showing only plain text files. |
+| Code Sample | Description |
+|-----------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [Action Basics](./action_basics) | Action and Action Group patterns implementation, adds entries to the Tools menu. |
+| [Comparing References Inspection](./comparing_string_references_inspection) | Local Inspection Tool, adds entries to **Settings | Editor | Inspections | Java | Probable Bugs**. |
+| [Conditional Operator Intention](./conditional_operator_intention) | Intention action, suggests converting a ternary operator into an `if` block and adds entry to **Settings | Editor | Intentions | SDK Intentions**. |
+| [Editor Basics](./editor_basics) | Basic Editor APIs example with editor popup menu with extra actions. |
+| [Framework Basics](./framework_basics) | Basic *SDK Demo Framework* support added to the **File | New | Project | Java** wizard. |
+| [Kotlin Demo](./kotlin_demo) | Kotlin example extending the *Main Menu* with a **Greeting** menu group. |
+| [Live Templates](./live_templates) | Live templates for Markdown language, adds an entry to the **Settings | Editor | Live Templates** dialog. |
+| [Max Opened Projects](./max_opened_projects) | Application services and listeners, shows warning dialog when more than 3 open projects are opened. |
+| [Module](./module) | *SDK Demo Module* module type added to the **File | New | Project...** wizard. |
+| [Product Specific - PyCharm Sample](./product_specific/pycharm_basics) | Plugin project configuration for the PyCharm IDE. |
+| [Project Model](./project_model) | Interacts with the project model, adds menu items to **Tools** and **Editor Context** menus. |
+| [Project View Pane](./project_view_pane) | Project View Pane listing only image files. |
+| [Project Wizard](./project_wizard) | Project Wizard example with demo steps. |
+| [PSI Demo](./psi_demo) | PSI Navigation features presentation. |
+| [Run Configuration](./run_configuration) | Run configuration implementation with factory, options and UI. |
+| [Settings](./settings) | Custom settings panel, adds a settings panel to the **Settings** panel under **Tools**. |
+| [Simple Language Plugin](./simple_language_plugin) | Custom language support, defines a new *Simple language* with syntax highlighting, annotations, code completion, and other features. |
+| [Theme Basics](./theme_basics) | Sample *theme* plugin with basic interface modifications. |
+| [Tool Window](./tool_window) | Custom Tool Window example plugin. |
+| [Tree Structure Provider](./tree_structure_provider) | Tree Structure Provider showing only plain text files. |
[gh:workflow-code-samples]: https://github.com/JetBrains/intellij-sdk-docs/actions/workflows/code-samples.yml
[gh:template]: https://github.com/JetBrains/intellij-platform-plugin-template
diff --git a/_gradleCompositeBuild/settings.gradle.kts b/_gradleCompositeBuild/settings.gradle.kts
index 25a98dfd0..0f96b40ab 100644
--- a/_gradleCompositeBuild/settings.gradle.kts
+++ b/_gradleCompositeBuild/settings.gradle.kts
@@ -5,7 +5,7 @@
rootProject.name = "SDK Code Samples"
includeBuild("../action_basics")
-includeBuild("../comparing_references_inspection")
+includeBuild("../comparing_string_references_inspection")
includeBuild("../conditional_operator_intention")
includeBuild("../editor_basics")
includeBuild("../facet_basics")
diff --git a/comparing_references_inspection/src/main/java/org/intellij/sdk/codeInspection/ComparingReferencesInspection.java b/comparing_references_inspection/src/main/java/org/intellij/sdk/codeInspection/ComparingReferencesInspection.java
deleted file mode 100644
index 792c39882..000000000
--- a/comparing_references_inspection/src/main/java/org/intellij/sdk/codeInspection/ComparingReferencesInspection.java
+++ /dev/null
@@ -1,203 +0,0 @@
-// Copyright 2000-2022 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-
-package org.intellij.sdk.codeInspection;
-
-import com.intellij.codeInspection.*;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.ui.DocumentAdapter;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import javax.swing.event.DocumentEvent;
-import java.awt.*;
-import java.util.StringTokenizer;
-
-import static com.siyeh.ig.psiutils.ExpressionUtils.isNullLiteral;
-
-/**
- * Implements an inspection to detect when object references are compared using 'a==b' or 'a!=b'.
- * The quick fix converts these comparisons to 'a.equals(b) or '!a.equals(b)' respectively.
- */
-public class ComparingReferencesInspection extends AbstractBaseJavaLocalInspectionTool {
-
- // Defines the text of the quick fix intention
- public static final String QUICK_FIX_NAME = "SDK: " +
- InspectionsBundle.message("inspection.comparing.references.use.quickfix");
- private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ComparingReferencesInspection");
- private final CriQuickFix myQuickFix = new CriQuickFix();
- // This string holds a list of classes relevant to this inspection.
- @SuppressWarnings({"WeakerAccess"})
- @NonNls
- public String CHECKED_CLASSES = "java.lang.String;java.util.Date";
-
- /**
- * This method is called to get the panel describing the inspection.
- * It is called every time the user selects the inspection in preferences.
- * The user has the option to edit the list of {@link #CHECKED_CLASSES}.
- *
- * @return panel to display inspection information.
- */
- @Override
- public JComponent createOptionsPanel() {
- JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
- final JTextField checkedClasses = new JTextField(CHECKED_CLASSES);
- checkedClasses.getDocument().addDocumentListener(new DocumentAdapter() {
- public void textChanged(@NotNull DocumentEvent event) {
- CHECKED_CLASSES = checkedClasses.getText();
- }
- });
- panel.add(checkedClasses);
- return panel;
- }
-
- /**
- * This method is overridden to provide a custom visitor.
- * that inspects expressions with relational operators '==' and '!='.
- * The visitor must not be recursive and must be thread-safe.
- *
- * @param holder object for visitor to register problems found.
- * @param isOnTheFly true if inspection was run in non-batch mode
- * @return non-null visitor for this inspection.
- * @see JavaElementVisitor
- */
- @NotNull
- @Override
- public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
- return new JavaElementVisitor() {
-
- /**
- * This string defines the short message shown to a user signaling the inspection found a problem.
- * It reuses a string from the inspections bundle.
- */
- @NonNls
- private final String DESCRIPTION_TEMPLATE = "SDK " +
- InspectionsBundle.message("inspection.comparing.references.problem.descriptor");
-
- /**
- * Avoid defining visitors for both Reference and Binary expressions.
- *
- * @param psiReferenceExpression The expression to be evaluated.
- */
- @Override
- public void visitReferenceExpression(PsiReferenceExpression psiReferenceExpression) {
- }
-
- /**
- * Evaluate binary psi expressions to see if they contain relational operators '==' and '!=', AND they contain
- * classes contained in CHECKED_CLASSES. The evaluation ignores expressions comparing an object to null.
- * IF this criteria is met, add the expression to the problems list.
- *
- * @param expression The binary expression to be evaluated.
- */
- @Override
- public void visitBinaryExpression(PsiBinaryExpression expression) {
- super.visitBinaryExpression(expression);
- IElementType opSign = expression.getOperationTokenType();
- if (opSign == JavaTokenType.EQEQ || opSign == JavaTokenType.NE) {
- // The binary expression is the correct type for this inspection
- PsiExpression lOperand = expression.getLOperand();
- PsiExpression rOperand = expression.getROperand();
- if (rOperand == null || isNullLiteral(lOperand) || isNullLiteral(rOperand)) {
- return;
- }
- // Nothing is compared to null, now check the types being compared
- PsiType lType = lOperand.getType();
- PsiType rType = rOperand.getType();
- if (isCheckedType(lType) || isCheckedType(rType)) {
- // Identified an expression with potential problems, add to list with fix object.
- holder.registerProblem(expression,
- DESCRIPTION_TEMPLATE, myQuickFix);
- }
- }
- }
-
- /**
- * Verifies the input is the correct {@code PsiType} for this inspection.
- *
- * @param type The {@code PsiType} to be examined for a match
- * @return {@code true} if input is {@code PsiClassType} and matches one of the classes
- * in the {@link ComparingReferencesInspection#CHECKED_CLASSES} list.
- */
- private boolean isCheckedType(PsiType type) {
- if (!(type instanceof PsiClassType)) {
- return false;
- }
- StringTokenizer tokenizer = new StringTokenizer(CHECKED_CLASSES, ";");
- while (tokenizer.hasMoreTokens()) {
- String className = tokenizer.nextToken();
- if (type.equalsToText(className)) {
- return true;
- }
- }
- return false;
- }
-
- };
- }
-
- /**
- * This class provides a solution to inspection problem expressions by manipulating the PSI tree to use 'a.equals(b)'
- * instead of '==' or '!='.
- */
- private static class CriQuickFix implements LocalQuickFix {
-
- /**
- * Returns a partially localized string for the quick fix intention.
- * Used by the test code for this plugin.
- *
- * @return Quick fix short name.
- */
- @NotNull
- @Override
- public String getName() {
- return QUICK_FIX_NAME;
- }
-
- /**
- * This method manipulates the PSI tree to replace 'a==b' with 'a.equals(b)' or 'a!=b' with '!a.equals(b)'.
- *
- * @param project The project that contains the file being edited.
- * @param descriptor A problem found by this inspection.
- */
- public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
- try {
- PsiBinaryExpression binaryExpression = (PsiBinaryExpression) descriptor.getPsiElement();
- IElementType opSign = binaryExpression.getOperationTokenType();
- PsiExpression lExpr = binaryExpression.getLOperand();
- PsiExpression rExpr = binaryExpression.getROperand();
- if (rExpr == null) {
- return;
- }
-
- PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
- PsiMethodCallExpression equalsCall =
- (PsiMethodCallExpression) factory.createExpressionFromText("a.equals(b)", null);
-
- equalsCall.getMethodExpression().getQualifierExpression().replace(lExpr);
- equalsCall.getArgumentList().getExpressions()[0].replace(rExpr);
-
- PsiExpression result = (PsiExpression) binaryExpression.replace(equalsCall);
-
- if (opSign == JavaTokenType.NE) {
- PsiPrefixExpression negation = (PsiPrefixExpression) factory.createExpressionFromText("!a", null);
- negation.getOperand().replace(result);
- result.replace(negation);
- }
- } catch (IncorrectOperationException e) {
- LOG.error(e);
- }
- }
-
- @NotNull
- public String getFamilyName() {
- return getName();
- }
-
- }
-
-}
diff --git a/comparing_references_inspection/src/main/resources/inspectionDescriptions/ComparingReferences.html b/comparing_references_inspection/src/main/resources/inspectionDescriptions/ComparingReferences.html
deleted file mode 100644
index 292ad9dad..000000000
--- a/comparing_references_inspection/src/main/resources/inspectionDescriptions/ComparingReferences.html
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-Reports usages of ==
and !=
when comparing instances of specified types.
-
- Quick-fix replaces operator with equals()
call.
-
-
-Configure the inspection:
-List classes to be inspected separated by semi-colon.
-
-
diff --git a/comparing_references_inspection/src/test/testData/Eq.after.java b/comparing_references_inspection/src/test/testData/Eq.after.java
deleted file mode 100644
index 20a37653b..000000000
--- a/comparing_references_inspection/src/test/testData/Eq.after.java
+++ /dev/null
@@ -1,6 +0,0 @@
-public class Eq {
- public boolean compare2Strings(java.lang.String s1, java.lang.String s2) {
- return (s1.equals(s2));
- }
-
-}
\ No newline at end of file
diff --git a/comparing_references_inspection/src/test/testData/Eq.java b/comparing_references_inspection/src/test/testData/Eq.java
deleted file mode 100644
index 43e40a40b..000000000
--- a/comparing_references_inspection/src/test/testData/Eq.java
+++ /dev/null
@@ -1,6 +0,0 @@
-public class Eq {
- public boolean compare2Strings(java.lang.String s1, java.lang.String s2) {
- return (s1 == s2);
- }
-
-}
\ No newline at end of file
diff --git a/comparing_references_inspection/src/test/testData/Neq.after.java b/comparing_references_inspection/src/test/testData/Neq.after.java
deleted file mode 100644
index 440f8bf4a..000000000
--- a/comparing_references_inspection/src/test/testData/Neq.after.java
+++ /dev/null
@@ -1,6 +0,0 @@
-public class Neq {
-public boolean compare2Dates(java.util.Date dt1, java.util.Date dt2){
- return (!dt1.equals(dt2));
- }
-
-}
\ No newline at end of file
diff --git a/comparing_references_inspection/src/test/testData/Neq.java b/comparing_references_inspection/src/test/testData/Neq.java
deleted file mode 100644
index aa7a04f22..000000000
--- a/comparing_references_inspection/src/test/testData/Neq.java
+++ /dev/null
@@ -1,6 +0,0 @@
-public class Neq {
-public boolean compare2Dates(java.util.Date dt1, java.util.Date dt2){
- return (dt1 != dt2);
- }
-
-}
\ No newline at end of file
diff --git a/comparing_references_inspection/README.md b/comparing_string_references_inspection/README.md
similarity index 65%
rename from comparing_references_inspection/README.md
rename to comparing_string_references_inspection/README.md
index fc6580ca3..719c54405 100644
--- a/comparing_references_inspection/README.md
+++ b/comparing_string_references_inspection/README.md
@@ -5,14 +5,14 @@
Comparing References Inspection Sample demonstrates the implementation of the [Code Inspections][docs:code_inspections] feature for Java classes.
-The plugin inspects your Java code and highlights any fragments containing the comparison of two `String` or `Date` variables.
+The plugin inspects your Java code and highlights any fragments containing the comparison of two `String` variables.
If such a check finds a comparison using the `==` or !`=` operators instead of the `.equals()` method, the plugin proposes a *quick-fix* action.
### Extension Points
-| Name | Implementation | Extension Point Class |
-|--------------------------------|---------------------------------------------------------------------|---------------------------------------|
-| `com.intellij.localInspection` | [ComparingReferencesInspection][file:ComparingReferencesInspection] | `AbstractBaseJavaLocalInspectionTool` |
+| Name | Implementation | Extension Point Class |
+|--------------------------------|---------------------------------------------------------------------------------|---------------------------------------|
+| `com.intellij.localInspection` | [ComparingStringReferencesInspection][file:ComparingStringReferencesInspection] | `AbstractBaseJavaLocalInspectionTool` |
*Reference: [Plugin Extension Points in IntelliJ SDK Docs][docs:ep]*
@@ -21,4 +21,4 @@ If such a check finds a comparison using the `==` or !`=` operators instead of t
[docs:code_inspections]: https://plugins.jetbrains.com/docs/intellij/code-inspections.html
[docs:ep]: https://plugins.jetbrains.com/docs/intellij/plugin-extensions.html
-[file:ComparingReferencesInspection]: ./src/main/java/org/intellij/sdk/codeInspection/ComparingReferencesInspection.java
+[file:ComparingStringReferencesInspection]: ./src/main/java/org/intellij/sdk/codeInspection/ComparingStringReferencesInspection.java
diff --git a/comparing_references_inspection/build.gradle.kts b/comparing_string_references_inspection/build.gradle.kts
similarity index 71%
rename from comparing_references_inspection/build.gradle.kts
rename to comparing_string_references_inspection/build.gradle.kts
index c29ea8a5c..6a94a8bfa 100644
--- a/comparing_references_inspection/build.gradle.kts
+++ b/comparing_string_references_inspection/build.gradle.kts
@@ -1,4 +1,4 @@
-// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
plugins {
id("java")
@@ -36,10 +36,4 @@ tasks {
sinceBuild.set("221")
untilBuild.set("223.*")
}
-
- test {
- // Set idea.home.path to the absolute path to the intellij-community source
- // on your local machine.
- systemProperty("idea.home.path", "/Users/jhake/Documents/source/comm")
- }
}
diff --git a/comparing_references_inspection/gradle/wrapper/gradle-wrapper.jar b/comparing_string_references_inspection/gradle/wrapper/gradle-wrapper.jar
similarity index 100%
rename from comparing_references_inspection/gradle/wrapper/gradle-wrapper.jar
rename to comparing_string_references_inspection/gradle/wrapper/gradle-wrapper.jar
diff --git a/comparing_references_inspection/gradle/wrapper/gradle-wrapper.properties b/comparing_string_references_inspection/gradle/wrapper/gradle-wrapper.properties
similarity index 100%
rename from comparing_references_inspection/gradle/wrapper/gradle-wrapper.properties
rename to comparing_string_references_inspection/gradle/wrapper/gradle-wrapper.properties
diff --git a/comparing_references_inspection/gradlew b/comparing_string_references_inspection/gradlew
similarity index 100%
rename from comparing_references_inspection/gradlew
rename to comparing_string_references_inspection/gradlew
diff --git a/comparing_references_inspection/gradlew.bat b/comparing_string_references_inspection/gradlew.bat
similarity index 100%
rename from comparing_references_inspection/gradlew.bat
rename to comparing_string_references_inspection/gradlew.bat
diff --git a/comparing_references_inspection/settings.gradle.kts b/comparing_string_references_inspection/settings.gradle.kts
similarity index 67%
rename from comparing_references_inspection/settings.gradle.kts
rename to comparing_string_references_inspection/settings.gradle.kts
index 9e1df8ce4..f78a8b3d8 100644
--- a/comparing_references_inspection/settings.gradle.kts
+++ b/comparing_string_references_inspection/settings.gradle.kts
@@ -1,3 +1,3 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
-rootProject.name = "comparing_references_inspection"
+rootProject.name = "comparing_string_references_inspection"
diff --git a/comparing_string_references_inspection/src/main/java/org/intellij/sdk/codeInspection/ComparingStringReferencesInspection.java b/comparing_string_references_inspection/src/main/java/org/intellij/sdk/codeInspection/ComparingStringReferencesInspection.java
new file mode 100644
index 000000000..b59a399be
--- /dev/null
+++ b/comparing_string_references_inspection/src/main/java/org/intellij/sdk/codeInspection/ComparingStringReferencesInspection.java
@@ -0,0 +1,139 @@
+// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+
+package org.intellij.sdk.codeInspection;
+
+import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
+
+import static com.siyeh.ig.psiutils.ExpressionUtils.isNullLiteral;
+
+/**
+ * Implements an inspection to detect when String references are compared using 'a==b' or 'a!=b'.
+ * The quick fix converts these comparisons to 'a.equals(b) or '!a.equals(b)' respectively.
+ */
+public class ComparingStringReferencesInspection extends AbstractBaseJavaLocalInspectionTool {
+
+ private final ReplaceWithEqualsQuickFix myQuickFix = new ReplaceWithEqualsQuickFix();
+
+ /**
+ * This method is overridden to provide a custom visitor
+ * that inspects expressions with relational operators '==' and '!='.
+ * The visitor must not be recursive and must be thread-safe.
+ *
+ * @param holder object for the visitor to register problems found
+ * @param isOnTheFly true if inspection was run in non-batch mode
+ * @return non-null visitor for this inspection
+ * @see JavaElementVisitor
+ */
+ @NotNull
+ @Override
+ public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
+ return new JavaElementVisitor() {
+
+ /**
+ * Evaluate binary psi expressions to see if they contain relational operators '==' and '!=',
+ * AND they are of String type.
+ * The evaluation ignores expressions comparing an object to null.
+ * IF these criteria are met, register the problem in the ProblemsHolder.
+ *
+ * @param expression The binary expression to be evaluated.
+ */
+ @Override
+ public void visitBinaryExpression(PsiBinaryExpression expression) {
+ super.visitBinaryExpression(expression);
+ IElementType opSign = expression.getOperationTokenType();
+ if (opSign == JavaTokenType.EQEQ || opSign == JavaTokenType.NE) {
+ // The binary expression is the correct type for this inspection
+ PsiExpression lOperand = expression.getLOperand();
+ PsiExpression rOperand = expression.getROperand();
+ if (rOperand == null || isNullLiteral(lOperand) || isNullLiteral(rOperand)) {
+ return;
+ }
+ // Nothing is compared to null, now check the types being compared
+ if (isStringType(lOperand) || isStringType(rOperand)) {
+ // Identified an expression with potential problems, register problem with the quick fix object
+ holder.registerProblem(expression,
+ InspectionBundle.message("inspection.comparing.string.references.problem.descriptor"),
+ myQuickFix);
+ }
+ }
+ }
+
+ private boolean isStringType(PsiExpression operand) {
+ PsiType type = operand.getType();
+ if (!(type instanceof PsiClassType)) {
+ return false;
+ }
+ PsiClass resolvedType = ((PsiClassType) type).resolve();
+ if (resolvedType == null) {
+ return false;
+ }
+ return "java.lang.String".equals(resolvedType.getQualifiedName());
+ }
+
+ };
+ }
+
+ /**
+ * This class provides a solution to inspection problem expressions by manipulating the PSI tree to use 'a.equals(b)'
+ * instead of '==' or '!='.
+ */
+ private static class ReplaceWithEqualsQuickFix implements LocalQuickFix {
+
+ /**
+ * Returns a partially localized string for the quick fix intention.
+ * Used by the test code for this plugin.
+ *
+ * @return Quick fix short name.
+ */
+ @NotNull
+ @Override
+ public String getName() {
+ return InspectionBundle.message("inspection.comparing.string.references.use.quickfix");
+ }
+
+ /**
+ * This method manipulates the PSI tree to replace 'a==b' with 'a.equals(b)' or 'a!=b' with '!a.equals(b)'.
+ *
+ * @param project The project that contains the file being edited.
+ * @param descriptor A problem found by this inspection.
+ */
+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
+ PsiBinaryExpression binaryExpression = (PsiBinaryExpression) descriptor.getPsiElement();
+ IElementType opSign = binaryExpression.getOperationTokenType();
+ PsiExpression lExpr = binaryExpression.getLOperand();
+ PsiExpression rExpr = binaryExpression.getROperand();
+ if (rExpr == null) {
+ return;
+ }
+
+ PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
+ PsiMethodCallExpression equalsCall =
+ (PsiMethodCallExpression) factory.createExpressionFromText("a.equals(b)", null);
+
+ equalsCall.getMethodExpression().getQualifierExpression().replace(lExpr);
+ equalsCall.getArgumentList().getExpressions()[0].replace(rExpr);
+
+ PsiExpression result = (PsiExpression) binaryExpression.replace(equalsCall);
+
+ if (opSign == JavaTokenType.NE) {
+ PsiPrefixExpression negation = (PsiPrefixExpression) factory.createExpressionFromText("!a", null);
+ negation.getOperand().replace(result);
+ result.replace(negation);
+ }
+ }
+
+ @NotNull
+ public String getFamilyName() {
+ return getName();
+ }
+
+ }
+
+}
diff --git a/comparing_string_references_inspection/src/main/java/org/intellij/sdk/codeInspection/InspectionBundle.java b/comparing_string_references_inspection/src/main/java/org/intellij/sdk/codeInspection/InspectionBundle.java
new file mode 100644
index 000000000..f3fbcec52
--- /dev/null
+++ b/comparing_string_references_inspection/src/main/java/org/intellij/sdk/codeInspection/InspectionBundle.java
@@ -0,0 +1,27 @@
+// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+
+package org.intellij.sdk.codeInspection;
+
+import com.intellij.DynamicBundle;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.PropertyKey;
+
+public final class InspectionBundle extends DynamicBundle {
+
+ private static final InspectionBundle ourInstance = new InspectionBundle();
+
+ @NonNls
+ public static final String BUNDLE = "messages.InspectionBundle";
+
+ private InspectionBundle() {
+ super(BUNDLE);
+ }
+
+ public static @Nls String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key,
+ Object @NotNull ... params) {
+ return ourInstance.getMessage(key, params);
+ }
+
+}
diff --git a/comparing_references_inspection/src/main/resources/META-INF/plugin.xml b/comparing_string_references_inspection/src/main/resources/META-INF/plugin.xml
similarity index 59%
rename from comparing_references_inspection/src/main/resources/META-INF/plugin.xml
rename to comparing_string_references_inspection/src/main/resources/META-INF/plugin.xml
index 99358e841..bc0938d7f 100644
--- a/comparing_references_inspection/src/main/resources/META-INF/plugin.xml
+++ b/comparing_string_references_inspection/src/main/resources/META-INF/plugin.xml
@@ -1,4 +1,4 @@
-
+
@@ -35,37 +35,37 @@
+ implementationClass="org.intellij.sdk.codeInspection.ComparingStringReferencesInspection"/>
diff --git a/comparing_references_inspection/src/main/resources/META-INF/pluginIcon.svg b/comparing_string_references_inspection/src/main/resources/META-INF/pluginIcon.svg
similarity index 100%
rename from comparing_references_inspection/src/main/resources/META-INF/pluginIcon.svg
rename to comparing_string_references_inspection/src/main/resources/META-INF/pluginIcon.svg
diff --git a/comparing_string_references_inspection/src/main/resources/inspectionDescriptions/ComparingStringReferences.html b/comparing_string_references_inspection/src/main/resources/inspectionDescriptions/ComparingStringReferences.html
new file mode 100644
index 000000000..f68912c55
--- /dev/null
+++ b/comparing_string_references_inspection/src/main/resources/inspectionDescriptions/ComparingStringReferences.html
@@ -0,0 +1,9 @@
+
+
+
+Reports usages of ==
and !=
when comparing instances of String.
+
+ Quick-fix replaces operator with equals()
call.
+
+
+
diff --git a/comparing_string_references_inspection/src/main/resources/messages/InspectionBundle.properties b/comparing_string_references_inspection/src/main/resources/messages/InspectionBundle.properties
new file mode 100644
index 000000000..b480d8836
--- /dev/null
+++ b/comparing_string_references_inspection/src/main/resources/messages/InspectionBundle.properties
@@ -0,0 +1,5 @@
+# Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+
+inspection.comparing.string.references.display.name=SDK: '==' or '!=' used instead of 'equals()'
+inspection.comparing.string.references.problem.descriptor=SDK: String objects compared with equality operation
+inspection.comparing.string.references.use.quickfix=SDK: Use equals()
diff --git a/comparing_references_inspection/src/test/java/org/intellij/sdk/codeInspection/ComparingReferencesInspectionTest.java b/comparing_string_references_inspection/src/test/java/org/intellij/sdk/codeInspection/ComparingStringReferencesInspectionTest.java
similarity index 60%
rename from comparing_references_inspection/src/test/java/org/intellij/sdk/codeInspection/ComparingReferencesInspectionTest.java
rename to comparing_string_references_inspection/src/test/java/org/intellij/sdk/codeInspection/ComparingStringReferencesInspectionTest.java
index 263a535fc..d77cd8a9d 100644
--- a/comparing_references_inspection/src/test/java/org/intellij/sdk/codeInspection/ComparingReferencesInspectionTest.java
+++ b/comparing_string_references_inspection/src/test/java/org/intellij/sdk/codeInspection/ComparingStringReferencesInspectionTest.java
@@ -1,23 +1,31 @@
-// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.intellij.sdk.codeInspection;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.testFramework.TestDataPath;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
import java.util.List;
-/**
- * Class for testing ComparingReferencesInspection.
- * Requires {@code idea.home.path} to be set in build.gradle.kts.
- * doTest() does the work for individual test cases.
- */
-public class ComparingReferencesInspectionTest extends LightJavaCodeInsightFixtureTestCase {
+@TestDataPath("$CONTENT_ROOT/testData")
+public class ComparingStringReferencesInspectionTest extends LightJavaCodeInsightFixtureTestCase {
+
+ private static final String QUICK_FIX_NAME =
+ InspectionBundle.message("inspection.comparing.string.references.use.quickfix");
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ myFixture.enableInspections(new ComparingStringReferencesInspection());
+ // optimization: add a fake java.lang.String class to avoid loading all JDK classes for test
+ myFixture.addClass("package java.lang; public final class String {}");
+ }
/**
- * Defines path to files used for running tests.
+ * Defines the path to files used for running tests.
*
* @return The path from this module's root directory ($MODULE_WORKING_DIR$) to the
* directory containing files for these tests.
@@ -27,28 +35,6 @@ public class ComparingReferencesInspectionTest extends LightJavaCodeInsightFixtu
return "src/test/testData";
}
- /**
- * Given the name of a test file, runs comparing references inspection quick fix and tests
- * the results against a reference outcome file. File name pattern 'foo.java' and 'foo.after.java'
- * are matching before and after files in the testData directory.
- *
- * @param testName The name of the test file before comparing references inspection.
- */
- protected void doTest(@NotNull String testName) {
- // Initialize the test based on the testData file
- myFixture.configureByFile(testName + ".java");
- // Initialize the inspection and get a list of highlighted
- myFixture.enableInspections(new ComparingReferencesInspection());
- List highlightInfos = myFixture.doHighlighting();
- assertFalse(highlightInfos.isEmpty());
- // Get the quick fix action for comparing references inspection and apply it to the file
- final IntentionAction action = myFixture.findSingleIntention(ComparingReferencesInspection.QUICK_FIX_NAME);
- assertNotNull(action);
- myFixture.launchAction(action);
- // Verify the results
- myFixture.checkResultByFile(testName + ".after.java");
- }
-
/**
* Test the '==' case.
*/
@@ -63,4 +49,26 @@ public class ComparingReferencesInspectionTest extends LightJavaCodeInsightFixtu
doTest("Neq");
}
+ /**
+ * Given the name of a test file, runs comparing references inspection quick fix and tests
+ * the results against a reference outcome file.
+ * File name pattern 'foo.java' and 'foo.after.java' are matching before and after files
+ * in the testData directory.
+ *
+ * @param testName test file name base
+ */
+ protected void doTest(@NotNull String testName) {
+ // Initialize the test based on the testData file
+ myFixture.configureByFile(testName + ".java");
+ // Initialize the inspection and get a list of highlighted
+ List highlightInfos = myFixture.doHighlighting();
+ assertFalse(highlightInfos.isEmpty());
+ // Get the quick fix action for comparing references inspection and apply it to the file
+ final IntentionAction action = myFixture.findSingleIntention(QUICK_FIX_NAME);
+ assertNotNull(action);
+ myFixture.launchAction(action);
+ // Verify the results
+ myFixture.checkResultByFile(testName + ".after.java");
+ }
+
}
diff --git a/comparing_string_references_inspection/src/test/testData/Eq.after.java b/comparing_string_references_inspection/src/test/testData/Eq.after.java
new file mode 100644
index 000000000..f4afd6dbc
--- /dev/null
+++ b/comparing_string_references_inspection/src/test/testData/Eq.after.java
@@ -0,0 +1,5 @@
+public class Eq {
+ public boolean compareStrings(String s1, String s2) {
+ return (s1.equals(s2));
+ }
+}
diff --git a/comparing_string_references_inspection/src/test/testData/Eq.java b/comparing_string_references_inspection/src/test/testData/Eq.java
new file mode 100644
index 000000000..2a8e3951e
--- /dev/null
+++ b/comparing_string_references_inspection/src/test/testData/Eq.java
@@ -0,0 +1,5 @@
+public class Eq {
+ public boolean compareStrings(String s1, String s2) {
+ return (s1 == s2);
+ }
+}
diff --git a/comparing_string_references_inspection/src/test/testData/Neq.after.java b/comparing_string_references_inspection/src/test/testData/Neq.after.java
new file mode 100644
index 000000000..dafe06016
--- /dev/null
+++ b/comparing_string_references_inspection/src/test/testData/Neq.after.java
@@ -0,0 +1,5 @@
+public class Neq {
+ public boolean compareStrings(String s1, String s2) {
+ return (!s1.equals(s2));
+ }
+}
diff --git a/comparing_string_references_inspection/src/test/testData/Neq.java b/comparing_string_references_inspection/src/test/testData/Neq.java
new file mode 100644
index 000000000..4bf437dc0
--- /dev/null
+++ b/comparing_string_references_inspection/src/test/testData/Neq.java
@@ -0,0 +1,5 @@
+public class Neq {
+ public boolean compareStrings(String s1, String s2) {
+ return (s1 != s2);
+ }
+}