mirror of
https://github.com/JetBrains/intellij-sdk-code-samples.git
synced 2025-07-27 16:57:49 +08:00
Port to Gradle, update unit tests
This commit is contained in:
parent
5b4867b2be
commit
722c5c656e
@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
@ -35,6 +35,3 @@ intellij {
|
||||
patchPluginXml {
|
||||
version = project.version
|
||||
}
|
||||
|
||||
// Force javadoc rebuild before jar is built
|
||||
jar.dependsOn javadoc
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
|
||||
|
@ -1,73 +0,0 @@
|
||||
<!-- Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
|
||||
<idea-plugin>
|
||||
<!-- Unique id for this plugin. Must stay constant for the life of the plugin. -->
|
||||
<id>org.intelliJ.sdk.codeInspection</id>
|
||||
|
||||
<!-- Text to display as name on Preferences/Settings | Plugin page -->
|
||||
<name>SDK Comparing References Inspection Sample</name>
|
||||
|
||||
<!-- The version of this plugin -->
|
||||
<version>1.1.0</version>
|
||||
|
||||
<!-- Compatible with the following versions of IntelliJ Platform -->
|
||||
<idea-version since-build="173"/>
|
||||
|
||||
<!-- Product and plugin compatibility requirements -->
|
||||
<depends>com.intellij.modules.java</depends>
|
||||
|
||||
<!-- Text to display as description on Preferences/Settings | Plugin page -->
|
||||
<description>
|
||||
<![CDATA[
|
||||
Demonstrates implementing a Local Inspection Tool.<br> Adds entries to <b>Preferences | Editor | Inspections | Java | Probable Bugs</b>.
|
||||
]]>
|
||||
</description>
|
||||
<change-notes>
|
||||
<![CDATA[
|
||||
<ul>
|
||||
<li><b>1.1.0</b> Refactor resources, register this inspection.</li>
|
||||
<li><b>1.0.0</b> Release 2018.3 and earlier.</li>
|
||||
</ul>
|
||||
]]>
|
||||
</change-notes>
|
||||
|
||||
<!-- Text to display as company information on Preferences/Settings | Plugin page -->
|
||||
<vendor url="https://plugins.jetbrains.com">IntelliJ Platform SDK</vendor>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
|
||||
<!-- Extend the IntelliJ Platform local inspection type, and connect it to the implementation class
|
||||
in this plugin.
|
||||
<localInspection> type element is applied within the scope of a file under edit.
|
||||
It is preferred over <inspectionToolProvider>
|
||||
@see intellij.platform.resources.LangExtensionPoints
|
||||
@see com.intellij.codeInspection.InspectionProfileEntry
|
||||
Attributes:
|
||||
language= Language ID
|
||||
shortName= Not specified, will be computed by the underlying implementation classes.
|
||||
displayName= The string to be shown in the Preferences | Editor | Inspections panel
|
||||
The displayName gets registered to identify this inspection.
|
||||
Can be localized using key= and bundle= attributes instead.
|
||||
groupPath= Defines the outermost grouping for this inspection in
|
||||
the Preferences | Editor | Inspections panel. Not localized.
|
||||
groupBundle= Name of *.bundle file to translate groupKey.
|
||||
In this case reuse an IntelliJ Platform bundle file from intellij.platform.resources.en
|
||||
groupKey= Key to use for translation subgroup name using groupBundle file.
|
||||
In this case reuse the IntelliJ Platform subcategory "Probable bugs"
|
||||
enabledByDefault= Inspection state when Inspections panel is created.
|
||||
level= The default level of error found by this inspection, e.g. INFO, ERROR, etc.
|
||||
@see com.intellij.codeHighlighting.HighlightDisplayLevel
|
||||
implementationClass= FQN of inspection implementation
|
||||
-->
|
||||
<localInspection language="JAVA"
|
||||
displayName="SDK: '==' or '!=' used instead of 'equals()'"
|
||||
groupPath="Java"
|
||||
groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.probable.bugs"
|
||||
enabledByDefault="true"
|
||||
level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.ComparingReferencesInspection"/>
|
||||
|
||||
</extensions>
|
||||
|
||||
</idea-plugin>
|
@ -1,7 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<b>SDK:</b> This inspection reports when the '==' or '!=' operator was used between expressions of
|
||||
reference types. <br>
|
||||
Classes to be inspected are controlled by a semi-colon separated <i>Options</i> list in the preferences panel for this inspection.
|
||||
</body>
|
||||
</html>
|
@ -1,199 +0,0 @@
|
||||
package 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;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
* @author jhake
|
||||
*/
|
||||
public class ComparingReferencesInspection extends AbstractBaseJavaLocalInspectionTool {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ComparingReferencesInspection");
|
||||
private final CriQuickFix myQuickFix = new CriQuickFix();
|
||||
|
||||
// Defines the text of the quick fix intention
|
||||
public static final String QUICK_FIX_NAME = "SDK: " + InspectionsBundle.message("inspection.comparing.references.use.quickfix");
|
||||
|
||||
// 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 CHECKED_CLASSES.
|
||||
* Adds a document listener to see if
|
||||
*
|
||||
* @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(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 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. 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.*;
|
||||
@ -18,8 +20,8 @@ import java.util.StringTokenizer;
|
||||
import static com.siyeh.ig.psiutils.ExpressionUtils.isNullLiteral;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
* @author jhake
|
||||
* 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 {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ComparingReferencesInspection");
|
||||
@ -46,7 +48,7 @@ public class ComparingReferencesInspection extends AbstractBaseJavaLocalInspecti
|
||||
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||
final JTextField checkedClasses = new JTextField(CHECKED_CLASSES);
|
||||
checkedClasses.getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
public void textChanged(DocumentEvent event) {
|
||||
public void textChanged(@NotNull DocumentEvent event) {
|
||||
CHECKED_CLASSES = checkedClasses.getText();
|
||||
}
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<!-- Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
|
||||
<idea-plugin>
|
||||
<!-- Unique id for this plugin. Must stay constant for the life of the plugin. -->
|
||||
@ -11,9 +11,9 @@
|
||||
<version>2.0.0</version>
|
||||
|
||||
<!-- Compatible with the following versions of IntelliJ Platform -->
|
||||
<idea-version since-build="171"/>
|
||||
<idea-version since-build="193.3"/>
|
||||
|
||||
<!-- Product and plugin compatibility requirements -->
|
||||
<!-- Evaluates java PSI -->
|
||||
<depends>com.intellij.modules.java</depends>
|
||||
|
||||
<!-- Text to display as description on Preferences/Settings | Plugin page -->
|
||||
|
@ -1,62 +0,0 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. 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.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
/**
|
||||
* -ea -Xbootclasspath/p:../out/classes/production/boot -XX:+HeapDumpOnOutOfMemoryError -Xmx512m -XX:MaxPermSize=320m
|
||||
* -Didea.system.path=../test-system -Didea.home.path=../ -Didea.config.path=../test-config -Didea.test.group=ALL_EXCLUDE_DEFINED
|
||||
*/
|
||||
public class CompRefInspTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
|
||||
/**
|
||||
* Returns path to the test data relative to "idea.home.path" defined in build.gradle.
|
||||
*/
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "sdk/code_samples/comparing_references_inspection/src/test/testData";
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the requirements for this project needed in this test,
|
||||
* such as the module type, the configured SDK, facets, libraries, etc.
|
||||
* @return
|
||||
*/
|
||||
@NotNull
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
return LightJavaCodeInsightFixtureTestCase.JAVA_8_ANNOTATED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the "==" case
|
||||
* Note the hint must match CriQuickFix#getName
|
||||
*
|
||||
*/
|
||||
public void testRelationalEq() {
|
||||
myFixture.configureByFiles("before.java");
|
||||
final IntentionAction action = myFixture.findSingleIntention(ComparingReferencesInspection.QUICK_FIX_NAME);
|
||||
assertNotNull(action);
|
||||
myFixture.launchAction(action);
|
||||
myFixture.checkResultByFile("before.after.java");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the "!=" case
|
||||
* Note the hint must match CriQuickFix#getName
|
||||
*
|
||||
*/
|
||||
public void testRelationalNeq() {
|
||||
myFixture.configureByFiles("before1.java");
|
||||
final IntentionAction action = myFixture.findSingleIntention(ComparingReferencesInspection.QUICK_FIX_NAME);
|
||||
assertNotNull(action);
|
||||
myFixture.launchAction(action);
|
||||
myFixture.checkResultByFile("before1.after.java");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. 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.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class for testing ComparingReferencesInspection.
|
||||
* Requires idea.home.path to be set in build.gradle
|
||||
* doTest() does the work for individual test cases.
|
||||
*/
|
||||
public class ComparingReferencesInspectionTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
|
||||
/**
|
||||
* Defines 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.
|
||||
*/
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return "src/test/resources";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) throws Throwable {
|
||||
// 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<HighlightInfo> 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
|
||||
*/
|
||||
public void testRelationalEq() throws Throwable {
|
||||
doTest("Eq");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the "!=" case
|
||||
*/
|
||||
public void testRelationalNeq() throws Throwable {
|
||||
doTest("Neq");
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
public class X {
|
||||
public class Eq {
|
||||
public boolean compare2Strings(java.lang.String s1, java.lang.String s2) {
|
||||
return (s1.equals(s2));
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
public class X {
|
||||
public class Eq {
|
||||
public boolean compare2Strings(java.lang.String s1, java.lang.String s2) {
|
||||
return (<caret>s1 == s2);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
public class X {
|
||||
public class Neq {
|
||||
public boolean compare2Dates(java.util.Date dt1, java.util.Date dt2){
|
||||
return (!dt1.equals(dt2));
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
public class X {
|
||||
public class Neq {
|
||||
public boolean compare2Dates(java.util.Date dt1, java.util.Date dt2){
|
||||
return (dt1 <caret>!= dt2);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user