mirror of
https://github.com/JetBrains/intellij-sdk-code-samples.git
synced 2025-07-30 18:27:49 +08:00
Migrate Intentions and Inspections tutorials from Confluence and minor fixes
- https://confluence.jetbrains.com/display/IDEADEV/Creation+of+Intention+Action -https://confluence.jetbrains.com/display/IDEADEV/Inspection+of+Code+Source
This commit is contained in:
parent
b063fac031
commit
e8f66fb06b
4
.idea/modules.xml
generated
4
.idea/modules.xml
generated
@ -2,7 +2,8 @@
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/code_samples/MaxOpenedProjects/MaxOpenedProjects.iml" filepath="$PROJECT_DIR$/code_samples/MaxOpenedProjects/MaxOpenedProjects.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/code_samples/comparing_references_inspection/comparing_references_inspection.iml" filepath="$PROJECT_DIR$/code_samples/comparing_references_inspection/comparing_references_inspection.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/code_samples/conditional_operator_intention/conditional_operator_intention.iml" filepath="$PROJECT_DIR$/code_samples/conditional_operator_intention/conditional_operator_intention.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/code_samples/editor_basics/editor_basics.iml" filepath="$PROJECT_DIR$/code_samples/editor_basics/editor_basics.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/code_samples/facet_basics/facet_basics.iml" filepath="$PROJECT_DIR$/code_samples/facet_basics/facet_basics.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/code_samples/framework/framework.iml" filepath="$PROJECT_DIR$/code_samples/framework/framework.iml" />
|
||||
@ -10,6 +11,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/code_samples/inspection/inspection.iml" filepath="$PROJECT_DIR$/code_samples/inspection/inspection.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/intellij-sdk-docs.iml" filepath="$PROJECT_DIR$/.idea/intellij-sdk-docs.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/code_sample/kotlin_demo/kotlin_demo.iml" filepath="$PROJECT_DIR$/code_sample/kotlin_demo/kotlin_demo.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/code_samples/max_opened_projects/max_opened_projects.iml" filepath="$PROJECT_DIR$/code_samples/max_opened_projects/max_opened_projects.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/code_samples/module/module.iml" filepath="$PROJECT_DIR$/code_samples/module/module.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/code_samples/plugin_sample/plugin_sample.iml" filepath="$PROJECT_DIR$/code_samples/plugin_sample/plugin_sample.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/code_samples/project_model/project_model.iml" filepath="$PROJECT_DIR$/code_samples/project_model/project_model.iml" />
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PLUGIN_MODULE" version="4">
|
||||
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/../../code_samples/kotlin_demo/resources/META-INF/plugin.xml" />
|
||||
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/source/META-INF/plugin.xml" />
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$/../../code_samples/kotlin_demo">
|
||||
<sourceFolder url="file://$MODULE_DIR$/../../code_samples/kotlin_demo/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/../../code_samples/kotlin_demo/resources" type="java-resource" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/source" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/testSource" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
@ -0,0 +1,14 @@
|
||||
<idea-plugin version="2">
|
||||
<name>Comparing References Inspection</name>
|
||||
<description>Inspection for (probably) inappropriate use of equality relation operation.</description>
|
||||
<version>1.0</version>
|
||||
<vendor>JetBrains</vendor>
|
||||
<!--
|
||||
<idea-version since-build="3000"/>
|
||||
-->
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<inspectionToolProvider implementation="com.intellij.codeInspection.ComparingReferencesProvider"/>
|
||||
</extensions>
|
||||
|
||||
</idea-plugin>
|
@ -0,0 +1,152 @@
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
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.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class ComparingReferencesInspection extends BaseJavaLocalInspectionTool {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ComparingReferencesInspection");
|
||||
|
||||
private final LocalQuickFix myQuickFix = new MyQuickFix();
|
||||
|
||||
@SuppressWarnings({"WeakerAccess"}) @NonNls public String CHECKED_CLASSES = "java.lang.String;java.util.Date";
|
||||
@NonNls private static final String DESCRIPTION_TEMPLATE = InspectionsBundle.message("inspection.comparing.references.problem.descriptor");
|
||||
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
|
||||
return "'==' or '!=' instead of 'equals()'";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getGroupDisplayName() {
|
||||
return GroupNames.BUGS_GROUP_NAME;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getShortName() {
|
||||
return "ComparingReferences";
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
|
||||
return new JavaElementVisitor() {
|
||||
|
||||
@Override
|
||||
public void visitReferenceExpression(PsiReferenceExpression psiReferenceExpression) {
|
||||
}
|
||||
|
||||
|
||||
@Override public void visitBinaryExpression(PsiBinaryExpression expression) {
|
||||
super.visitBinaryExpression(expression);
|
||||
IElementType opSign = expression.getOperationTokenType();
|
||||
if (opSign == JavaTokenType.EQEQ || opSign == JavaTokenType.NE) {
|
||||
PsiExpression lOperand = expression.getLOperand();
|
||||
PsiExpression rOperand = expression.getROperand();
|
||||
if (rOperand == null || isNullLiteral(lOperand) || isNullLiteral(rOperand)) return;
|
||||
|
||||
PsiType lType = lOperand.getType();
|
||||
PsiType rType = rOperand.getType();
|
||||
|
||||
if (isCheckedType(lType) || isCheckedType(rType)) {
|
||||
holder.registerProblem(expression,
|
||||
DESCRIPTION_TEMPLATE, myQuickFix);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean isNullLiteral(PsiExpression expr) {
|
||||
return expr instanceof PsiLiteralExpression && "null".equals(expr.getText());
|
||||
}
|
||||
|
||||
private static class MyQuickFix implements LocalQuickFix {
|
||||
@NotNull
|
||||
public String getName() {
|
||||
// The test (see the TestThisPlugin class) uses this string to identify the quick fix action.
|
||||
return InspectionsBundle.message("inspection.comparing.references.use.quickfix");
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public boolean isEnabledByDefault() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class ComparingReferencesProvider implements InspectionToolProvider {
|
||||
public Class[] getInspectionClasses() {
|
||||
return new Class[] { ComparingReferencesInspection.class};
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
This inspection reports when the '==' or '!=' operator was used between expressions of
|
||||
reference types. <br>
|
||||
In the text field below, specify the semicolon separated list of classes to be considered as suspicious.
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,6 @@
|
||||
public class X {
|
||||
public boolean compare2Strings(java.lang.String s1, java.lang.String s2) {
|
||||
return (s1.equals(s2));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
public class X {
|
||||
public boolean compare2Strings(java.lang.String s1, java.lang.String s2) {
|
||||
return (<caret>s1 == s2);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
public class X {
|
||||
public boolean compare2Dates(java.util.Date dt1, java.util.Date dt2){
|
||||
return (!dt1.equals(dt2));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
public class X {
|
||||
public boolean compare2Dates(java.util.Date dt1, java.util.Date dt2){
|
||||
return (dt1 <caret>!= dt2);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package testPlugin;
|
||||
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.ComparingReferencesInspection;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
|
||||
import com.intellij.testFramework.fixtures.*;
|
||||
import junit.framework.Assert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @see JavaCodeInsightFixtureTestCase
|
||||
* @see LightCodeInsightFixtureTestCase
|
||||
*/
|
||||
public class TestThisPlugin extends UsefulTestCase {
|
||||
|
||||
protected CodeInsightTestFixture myFixture;
|
||||
// Specify path to your test data directory
|
||||
// e.g. final String dataPath = "c:\\users\\john.doe\\idea\\community\\samples\\ComparingReferences/testData";
|
||||
final String dataPath = "c:\\users\\John.Doe\\idea\\community\\samples\\comparingReferences/testData";
|
||||
|
||||
|
||||
public void setUp() throws Exception {
|
||||
|
||||
final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory();
|
||||
final TestFixtureBuilder<IdeaProjectTestFixture> testFixtureBuilder = fixtureFactory.createFixtureBuilder(getName());
|
||||
myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(testFixtureBuilder.getFixture());
|
||||
myFixture.setTestDataPath(dataPath);
|
||||
final JavaModuleFixtureBuilder builder = testFixtureBuilder.addModule(JavaModuleFixtureBuilder.class);
|
||||
|
||||
builder.addContentRoot(myFixture.getTempDirPath()).addSourceRoot("");
|
||||
builder.setMockJdkLevel(JavaModuleFixtureBuilder.MockJdkLevel.jdk15);
|
||||
myFixture.setUp();
|
||||
}
|
||||
|
||||
public void tearDown() throws Exception {
|
||||
myFixture.tearDown();
|
||||
myFixture = null;
|
||||
}
|
||||
|
||||
protected void doTest(String testName, String hint) throws Throwable {
|
||||
myFixture.configureByFile(testName + ".java");
|
||||
myFixture.enableInspections(ComparingReferencesInspection.class);
|
||||
List<HighlightInfo> highlightInfos = myFixture.doHighlighting();
|
||||
Assert.assertTrue(!highlightInfos.isEmpty());
|
||||
|
||||
final IntentionAction action = myFixture.findSingleIntention(hint);
|
||||
|
||||
Assert.assertNotNull(action);
|
||||
myFixture.launchAction(action);
|
||||
myFixture.checkResultByFile(testName + ".after.java");
|
||||
}
|
||||
|
||||
// Test the "==" case
|
||||
public void test() throws Throwable {
|
||||
doTest("before", "Use equals()");
|
||||
}
|
||||
|
||||
// Test the "!=" case
|
||||
public void test1() throws Throwable {
|
||||
doTest("before1", "Use equals()");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<idea-plugin version="2">
|
||||
<name>Conditional Operator Converter</name>
|
||||
<id>ConditionalOperatorConverter</id>
|
||||
<description>Intention action that suggests to convert a conditional operator into
|
||||
'if' block.
|
||||
</description>
|
||||
<version>1.3</version>
|
||||
<vendor>JetBrains</vendor>
|
||||
<!--
|
||||
<idea-version since-build="2000"/>
|
||||
-->
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<intentionAction>
|
||||
<className>com.intellij.codeInsight.intention.ConditionalOperatorConvertor</className>
|
||||
<category>Conditional Operator</category>
|
||||
<descriptionDirectoryName>ConditionalOperatorConvertor</descriptionDirectoryName>
|
||||
|
||||
</intentionAction>
|
||||
</extensions>
|
||||
|
||||
<project-components>
|
||||
<component>
|
||||
<implementation-class>com.intellij.codeInsight.intention.ConditionalOperatorConvertor</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
</idea-plugin>
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PLUGIN_MODULE" version="4">
|
||||
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/source/META-INF/plugin.xml" />
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/source" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/testSource" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
@ -0,0 +1,35 @@
|
||||
<idea-plugin version="2">
|
||||
<id>com.your.company.unique.plugin.id</id>
|
||||
<name>Plugin display name here</name>
|
||||
<version>1.0</version>
|
||||
<vendor email="support@yourcompany.com" url="http://www.yourcompany.com">YourCompany</vendor>
|
||||
|
||||
<description><![CDATA[
|
||||
Enter short description for your plugin here.<br>
|
||||
<em>most HTML tags may be used</em>
|
||||
]]></description>
|
||||
|
||||
<change-notes><![CDATA[
|
||||
Add change notes here.<br>
|
||||
<em>most HTML tags may be used</em>
|
||||
]]>
|
||||
</change-notes>
|
||||
|
||||
<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
|
||||
<idea-version since-build="141.0"/>
|
||||
|
||||
<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
|
||||
on how to target different products -->
|
||||
<!-- uncomment to enable plugin in all products
|
||||
<depends>com.intellij.modules.lang</depends>
|
||||
-->
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<!-- Add your extensions here -->
|
||||
</extensions>
|
||||
|
||||
<actions>
|
||||
<!-- Add your actions here -->
|
||||
</actions>
|
||||
|
||||
</idea-plugin>
|
@ -0,0 +1,110 @@
|
||||
package com.intellij.codeInsight.intention;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author dsl
|
||||
*/
|
||||
@NonNls public class ConditionalOperatorConvertor extends PsiElementBaseIntentionAction implements IntentionAction {
|
||||
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return "Convert ternary operator to if statement";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, @Nullable PsiElement element) {
|
||||
if (element == null) return false;
|
||||
if (!element.isWritable()) return false;
|
||||
|
||||
if (element instanceof PsiJavaToken) {
|
||||
final PsiJavaToken token = (PsiJavaToken)element;
|
||||
if (token.getTokenType() != JavaTokenType.QUEST) return false;
|
||||
if (token.getParent() instanceof PsiConditionalExpression) {
|
||||
final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression)token.getParent();
|
||||
if (conditionalExpression.getThenExpression() == null
|
||||
|| conditionalExpression.getElseExpression() == null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
final int offset = editor.getCaretModel().getOffset();
|
||||
final PsiElement element = file.findElementAt(offset);
|
||||
PsiConditionalExpression conditionalExpression = PsiTreeUtil.getParentOfType(element,
|
||||
PsiConditionalExpression.class, false);
|
||||
if (conditionalExpression == null) return;
|
||||
if (conditionalExpression.getThenExpression() == null || conditionalExpression.getElseExpression() == null) return;
|
||||
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
|
||||
|
||||
PsiElement originalStatement = PsiTreeUtil.getParentOfType(conditionalExpression, PsiStatement.class, false);
|
||||
while (originalStatement instanceof PsiForStatement) {
|
||||
originalStatement = PsiTreeUtil.getParentOfType(originalStatement, PsiStatement.class, true);
|
||||
}
|
||||
if (originalStatement == null) return;
|
||||
|
||||
// Maintain declrations
|
||||
if (originalStatement instanceof PsiDeclarationStatement) {
|
||||
final PsiDeclarationStatement declaration = (PsiDeclarationStatement)originalStatement;
|
||||
final PsiElement[] declaredElements = declaration.getDeclaredElements();
|
||||
PsiLocalVariable variable = null;
|
||||
for (PsiElement declaredElement : declaredElements) {
|
||||
if (declaredElement instanceof PsiLocalVariable && PsiTreeUtil.isAncestor(declaredElement, conditionalExpression, true)) {
|
||||
variable = (PsiLocalVariable)declaredElement;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (variable == null) return;
|
||||
variable.normalizeDeclaration();
|
||||
final Object marker = new Object();
|
||||
PsiTreeUtil.mark(conditionalExpression, marker);
|
||||
PsiExpressionStatement statement =
|
||||
(PsiExpressionStatement)factory.createStatementFromText(variable.getName() + " = 0;", null);
|
||||
statement = (PsiExpressionStatement)CodeStyleManager.getInstance(project).reformat(statement);
|
||||
((PsiAssignmentExpression)statement.getExpression()).getRExpression().replace(variable.getInitializer());
|
||||
variable.getInitializer().delete();
|
||||
final PsiElement variableParent = variable.getParent();
|
||||
originalStatement = variableParent.getParent().addAfter(statement, variableParent);
|
||||
conditionalExpression = (PsiConditionalExpression)PsiTreeUtil.releaseMark(originalStatement, marker);
|
||||
}
|
||||
|
||||
// create then and else branches
|
||||
final PsiElement[] originalElements = new PsiElement[]{originalStatement, conditionalExpression};
|
||||
final PsiExpression condition = (PsiExpression)conditionalExpression.getCondition().copy();
|
||||
final PsiElement[] thenElements = PsiTreeUtil.copyElements(originalElements);
|
||||
final PsiElement[] elseElements = PsiTreeUtil.copyElements(originalElements);
|
||||
thenElements[1].replace(conditionalExpression.getThenExpression());
|
||||
elseElements[1].replace(conditionalExpression.getElseExpression());
|
||||
|
||||
PsiIfStatement statement = (PsiIfStatement)factory.createStatementFromText("if (true) { a = b } else { c = d }",
|
||||
null);
|
||||
statement = (PsiIfStatement)CodeStyleManager.getInstance(project).reformat(statement);
|
||||
statement.getCondition().replace(condition);
|
||||
statement = (PsiIfStatement)originalStatement.replace(statement);
|
||||
|
||||
((PsiBlockStatement)statement.getThenBranch()).getCodeBlock().getStatements()[0].replace(thenElements[0]);
|
||||
((PsiBlockStatement)statement.getElseBranch()).getCodeBlock().getStatements()[0].replace(elseElements[0]);
|
||||
}
|
||||
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
public class X {
|
||||
void f(boolean isMale) {
|
||||
String title;
|
||||
if (isMale) {
|
||||
title = "Mr.";
|
||||
} else {
|
||||
title = "Ms.";
|
||||
}
|
||||
System.out.println("title = " + title);
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
public class X {
|
||||
void f(boolean isMale) {
|
||||
String title = isMale <spot>?</spot> "Mr." : "Ms.";
|
||||
System.out.println("title = " + title);
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts a ternary operator to a corresponding if statement. <br>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,11 @@
|
||||
public class X {
|
||||
void f(boolean isMale) {
|
||||
String title;
|
||||
if (isMale) {
|
||||
title = "Mr.";
|
||||
} else {
|
||||
title = "Ms.";
|
||||
}
|
||||
System.out.println("title = " + title);
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
public class X {
|
||||
void f(boolean isMale) {
|
||||
String title = isMale <caret>? "Mr." : "Ms.";
|
||||
System.out.println("title = " + title);
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package testPlugin;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
|
||||
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
|
||||
import com.intellij.testFramework.fixtures.*;
|
||||
import junit.framework.Assert;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: Alexey.Chursin
|
||||
* Date: Sep 13, 2010
|
||||
* Time: 9:35:50 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
|
||||
public class YourTest {
|
||||
protected CodeInsightTestFixture myFixture;
|
||||
// Specify path to your test data
|
||||
// e.g. final String dataPath = "c:\\users\\john.doe\\idea\\community\\samples\\conditionalOperatorConvertor/testData";
|
||||
final String dataPath = "c:\\users\\John.Doe\\idea\\community\\samples\\conditionalOperatorConvertor/testData";
|
||||
|
||||
@Before
|
||||
|
||||
public void setUp() throws Exception {
|
||||
|
||||
final IdeaTestFixtureFactory fixtureFactory = IdeaTestFixtureFactory.getFixtureFactory();
|
||||
final TestFixtureBuilder<IdeaProjectTestFixture> testFixtureBuilder = fixtureFactory.createFixtureBuilder();
|
||||
myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(testFixtureBuilder.getFixture());
|
||||
myFixture.setTestDataPath(dataPath);
|
||||
final JavaModuleFixtureBuilder builder = testFixtureBuilder.addModule(JavaModuleFixtureBuilder.class);
|
||||
|
||||
builder.addContentRoot(myFixture.getTempDirPath()).addSourceRoot("");
|
||||
builder.setMockJdkLevel(JavaModuleFixtureBuilder.MockJdkLevel.jdk15);
|
||||
myFixture.setUp();
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
myFixture.tearDown();
|
||||
myFixture = null;
|
||||
}
|
||||
|
||||
protected void doTest(String testName, String hint) throws Throwable {
|
||||
// Messages.showInfoMessage("Test started", "Info");
|
||||
myFixture.configureByFile(testName + ".java");
|
||||
final IntentionAction action = myFixture.findSingleIntention(hint);
|
||||
Assert.assertNotNull(action);
|
||||
myFixture.launchAction(action);
|
||||
myFixture.checkResultByFile(testName + ".after.java");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Throwable {
|
||||
doTest("before.template", "Convert ternary operator to if statement");
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +1,8 @@
|
||||
https://confluence.jetbrains.com/pages/viewpage.action?pageId=15799219
|
||||
https://confluence.jetbrains.com/download/attachments/15799219/Presentation.pdf
|
||||
|
||||
https://confluence.jetbrains.com/display/IDEADEV/IntelliJ+IDEA+Notifications
|
||||
https://confluence.jetbrains.com/display/IDEADEV/Creation+of+Intention+Action
|
||||
https://confluence.jetbrains.com/display/IDEADEV/Inspection+of+Code+Source
|
||||
https://confluence.jetbrains.com/display/IDEADEV/ComparisonChainGen
|
||||
https://confluence.jetbrains.com/display/IDEADEV/Diana+Plugin+Migration+Guide
|
||||
https://confluence.jetbrains.com/display/IDEADEV/Customizing+the+IDEA+Settings+Dialog
|
||||
https://confluence.jetbrains.com/display/IDEADEV/Implementing+Run+Configurations+in+IntelliJ+IDEA
|
||||
https://confluence.jetbrains.com/display/IDEADEV/Remote+communication
|
||||
https://confluence.jetbrains.com/display/IDEADEV/Sample+Text+File+Editor
|
@ -2,4 +2,73 @@
|
||||
title: Code Inspections
|
||||
---
|
||||
|
||||
In Progress
|
||||
This topic describes the [comparing_refereces_inspection](https://github.com/JetBrains/intellij-sdk-docs/tree/master/code_samples/comparing_references_inspection), a sample plugin that creates a custom [inspection](http://www.jetbrains.com/idea/webhelp/code-inspection.html) for Java code. In addition, the sample plugin contains a JUnit-based test.
|
||||
|
||||
### About Code Inspections
|
||||
|
||||
**IntelliJ IDEA** provides tools designed for static code analysis (so called _code inspections_) that help you maintain and clean up your code without actually executing it. In **IntelliJ IDEA** you will find a set of built-in inspections that are grouped by their goals and sense. For more information about code inspections, see [Inspecting Source Code](http://www.jetbrains.com/idea/webhelp/inspecting-source-code.html) the in **IntelliJ IDEA** Web Help.
|
||||
|
||||
You can create custom inspections through the **IntelliJ IDEA** interface (see [Creating Own Inspections](http://www.jetbrains.com/idea/webhelp/creating-own-inspections.html)). Alternatively, you can develop a plugin to implement a custom inspection.
|
||||
|
||||
### Used Techniques
|
||||
|
||||
The **comparing_references_inspection** sample plugin illustrates the use of the following techniques:
|
||||
|
||||
- How to analyze a [PSI tree](http://confluence.jetbrains.net/display/IDEADEV/IntelliJ+IDEA+Architectural+Overview#PsiFiles).
|
||||
- How to find a Java token of interest in the PSI tree.
|
||||
- How to inspect Java code in the **IntelliJ IDEA** editor using the [BaseJavaLocalInspectionTool](upsource:///java/java-analysis-api/src/com/intellij/codeInspection/BaseJavaLocalInspectionTool.java) class.
|
||||
- How to create a JUnit test for this plugin using the [IdeaTestFixtureFactory](upsource:///platform/testFramework/src/com/intellij/testFramework/fixtures/IdeaTestFixtureFactory.java) class.
|
||||
|
||||
### Sample Plugin
|
||||
|
||||
The **comparingReferences** sample plugin is available in the `<%IntelliJ SDK Docs project%>/code_samples/comparing_references_inspection` directory.
|
||||
When launched, this plugin adds the **'==' or '!=' instead of 'equals()'** item to the **Probable bugs** node in the [Inspections list](http://www.jetbrains.com/idea/webhelp/inspections-2.html).
|
||||
|
||||

|
||||
|
||||
##### Running the Plugin
|
||||
|
||||
**To run the sample plugin**
|
||||
|
||||
1. Start **IntelliJ IDEA** and open the **comparingReferences** plugin project saved into the `<%IntelliJ SDK Docs project%>/code_samples/comparing_references_inspection` directory.
|
||||
2. Open the [Project Structure](http://www.jetbrains.com/idea/webhelp/project-structure.html) dialog and ensure that the project settings are valid for your environment.
|
||||
3. If necessary, modify the [Run/Debug Configurations](http://www.jetbrains.com/idea/webhelp/run-debug-configuration-plugin.html) and Run the plugin by choosing the **Run | Run** on the main menu.
|
||||
|
||||
##### Configuring the Plugin
|
||||
|
||||
Once the plugin is launched, you can set the plugin options. You can specify the Java classes to be participated in the code inspection and the severity level of the found probable bugs.
|
||||
|
||||
**To configure the sample plugin**
|
||||
|
||||
1. On the IDEA main menu, choose **File | Settings**, and then under **Project Settings**, click **Inspections**.
|
||||
2. In the list of the IntelliJ IDEA inspections, expand the **Probable bugs** node, and then click **'==' or '!=' instead of 'equals()'**.
|
||||

|
||||
3. Under **Options**, you can specify the following plugin settings:
|
||||
- From the **Severity** list, select the severity level of probable bugs the plugin will find (such as Warning, Info, etc.)
|
||||
- In the text box under **Severity**, specify the semicolon separated list of Java classes to be participated in this code inspection.
|
||||
4. When finished, click **OK**.
|
||||
|
||||
##### How does it work?
|
||||
|
||||
The plugin inspects your code opened in the **IntelliJ IDEA** editor or the code you are typing. The plugin highlights the code fragments where two variables of the reference type are separated by **==** or **!=** and proposes to replace this code fragment with **.equals()**:
|
||||
|
||||

|
||||
|
||||
In this example, the **s1** and **s2** are variables of the String type. Clicking **Use equals()** replaces
|
||||
|
||||
```java
|
||||
return (s1==s2);
|
||||
```
|
||||
|
||||
with the code:
|
||||
|
||||
```java
|
||||
return (s1.equals(s2));
|
||||
```
|
||||
|
||||
##### Testing the Plugin
|
||||
|
||||
The sample plugin contains the `TestThisPlugin` Java class in the `testSource/testPlugin` package and the test data in the `testData` directory.
|
||||
This test adds two test cases to this plugin project. To run test cases, run the `YourTest.test()` or `YourTest.test1()` method, respectively.
|
||||
|
||||
For detailed information about testing and all related procedures, refer to [Testing](http://www.jetbrains.com/idea/webhelp/testing.html) and [Testing Support](http://www.jetbrains.com/idea/webhelp/testing-support.html) in the **IntelliJ IDEA** Web Help.
|
70
tutorials/code_intentions.md
Normal file
70
tutorials/code_intentions.md
Normal file
@ -0,0 +1,70 @@
|
||||
---
|
||||
title: Code Intentions
|
||||
---
|
||||
|
||||
This topic describes the [conditional_operator_intention](https://github.com/JetBrains/intellij-sdk-docs/tree/master/code_samples/conditional_operator_intention), a sample plugin that adds a new [intention action](http://www.jetbrains.com/idea/webhelp/intention-actions.html) to the IntelliJ Platform Intentions list. In addition, the sample plugin contains a JUnit-based test.
|
||||
|
||||
### About Intention Actions
|
||||
|
||||
The **IntelliJ Platform** analyzes your code and helps handle situations that may result in errors. When a possible problem is suspected, the IDE suggests an appropriate intention action, denoted with special icons. For more information, refer to [Intention Actions](http://www.jetbrains.com/idea/webhelp/intention-actions.html) in the **IntelliJ IDEA** Web Help.
|
||||
|
||||
You can view a list of all available intention actions using the [Intention List](http://www.jetbrains.com/idea/webhelp/intentions.html#intentionList) provided by the IDE.
|
||||
|
||||
**To display Intention List**
|
||||
|
||||
1. Open the **Settings** dialog box.
|
||||
2. Under **IDE Settings**, click **Intentions**.
|
||||
This displays the list of all intention actions currently available in **IntelliJ IDEA**. The intention actions are grouped according to the areas of their use.
|
||||
To enable/disable an intention action, select/clear the check box to its left.
|
||||
|
||||
### Used Techniques
|
||||
|
||||
The **conditionalOperatorConverter** sample plugin illustrates the use of the following techniques:
|
||||
|
||||
- How to analyze a [PSI tree](http://confluence.jetbrains.net/display/IDEADEV/IntelliJ+IDEA+Architectural+Overview#PsiFiles).
|
||||
- How to find a Java token of interest in the PSI tree.
|
||||
- How to invoke a quick fix action for a token element under cursor using the [PsiElementBaseIntentionAction](upsource:///platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java) class.
|
||||
- How to create a JUnit test for this plugin using the [IdeaTestFixtureFactory](upsource:///platform/testFramework/src/com/intellij/testFramework/fixtures/IdeaTestFixtureFactory.java) class.
|
||||
|
||||
### Sample Plugin
|
||||
|
||||
The **ConditionalOperatorConverter** sample plugin is available in the `<%IntelliJ SDK Docs project%>/code_samples/conditional_operator_intention` directory. When launched, this plugin adds the **Convert ternary operator if statement** item to the **Conditional Operator** node in the IDEA Intentions list:
|
||||
|
||||

|
||||
|
||||
##### Running the Plugin
|
||||
|
||||
**To run the sample plugin**
|
||||
|
||||
1. Start **IntelliJ IDEA** and open the **conditionalOperatorConvertor** plugin project saved into the `<%IntelliJ SDK Docs project%>/code_samples/conditional_operator_intention` directory.
|
||||
2. Open the [Project Structure](http://www.jetbrains.com/idea/webhelp/project-structure.html) dialog and ensure that the project settings are valid for your environment.
|
||||
3. If necessary, modify the [Run/Debug Configurations](http://www.jetbrains.com/idea/webhelp/run-debug-configuration-plugin.html) and Run the plugin by choosing the **Run | Run** on the main menu.
|
||||
|
||||
##### How does it work?
|
||||
|
||||
The plugin analyzes symbols under the cursor in your code opened in the IDEA editor. If the cursor is positioned on the "?" conditional operator, **IntelliJ IDEA** proposes to replace this conditional (ternary) operator with the "if-then-else" statement:
|
||||
|
||||

|
||||
|
||||
In this example, the code:
|
||||
|
||||
```java
|
||||
return (n>=0) ? n : -n;
|
||||
```
|
||||
|
||||
will be replaced with the code:
|
||||
|
||||
```java
|
||||
if ((n>=0)) {
|
||||
return n;
|
||||
} else {
|
||||
return -n;
|
||||
}
|
||||
```
|
||||
|
||||
###### Testing the Plugin
|
||||
|
||||
The sample plugin contains the `YourTest` Java class in the `testSource/testPlugin/` package and the test data in the `testData/` directory.
|
||||
To perform the plugin test, run the `YourTest.test()` method.
|
||||
|
||||
For detailed information about testing and all related procedures, refer to [Testing](http://www.jetbrains.com/idea/webhelp/testing.html) and [Testing Support](http://www.jetbrains.com/idea/webhelp/testing-support.html) in the **IntelliJ IDEA** Web Help.
|
BIN
tutorials/img/IntentionsList.png
Normal file
BIN
tutorials/img/IntentionsList.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
BIN
tutorials/img/TernaryOperator.png
Normal file
BIN
tutorials/img/TernaryOperator.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
BIN
tutorials/img/comparingReferences.png
Normal file
BIN
tutorials/img/comparingReferences.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
BIN
tutorials/img/comparingReferences_options.png
Normal file
BIN
tutorials/img/comparingReferences_options.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
Loading…
x
Reference in New Issue
Block a user