First build for GH pages

This commit is contained in:
breandan considine 2016-01-14 19:38:06 -08:00
commit e2e94dadb4
164 changed files with 6302 additions and 0 deletions

View File

@ -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>

View File

@ -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;
}
}

View File

@ -0,0 +1,10 @@
package com.intellij.codeInspection;
/**
* @author max
*/
public class ComparingReferencesProvider implements InspectionToolProvider {
public Class[] getInspectionClasses() {
return new Class[] { ComparingReferencesInspection.class};
}
}

View File

@ -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>

View File

@ -0,0 +1,6 @@
public class X {
public boolean compare2Strings(java.lang.String s1, java.lang.String s2) {
return (s1.equals(s2));
}
}

View File

@ -0,0 +1,6 @@
public class X {
public boolean compare2Strings(java.lang.String s1, java.lang.String s2) {
return (<caret>s1 == s2);
}
}

View File

@ -0,0 +1,6 @@
public class X {
public boolean compare2Dates(java.util.Date dt1, java.util.Date dt2){
return (!dt1.equals(dt2));
}
}

View File

@ -0,0 +1,6 @@
public class X {
public boolean compare2Dates(java.util.Date dt1, java.util.Date dt2){
return (dt1 <caret>!= dt2);
}
}

View File

@ -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()");
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,6 @@
public class X {
void f(boolean isMale) {
String title = isMale <spot>?</spot> "Mr." : "Ms.";
System.out.println("title = " + title);
}
}

View File

@ -0,0 +1,5 @@
<html>
<body>
This intention converts a ternary operator to a corresponding if statement. <br>
</body>
</html>

View File

@ -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);
}
}

View File

@ -0,0 +1,6 @@
public class X {
void f(boolean isMale) {
String title = isMale <caret>? "Mr." : "Ms.";
System.out.println("title = " + title);
}
}

View File

@ -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");
}
}

View File

@ -0,0 +1,42 @@
<idea-plugin version="2" url="www.jetbrains.com">
<id>org.jetbrains.plugins.sample.EditorBasics</id>
<name>Editor basics</name>
<version>1.0</version>
<vendor email="support@jetbrains.com" url="http://www.jetbrains.com">JetBrains</vendor>
<description>Illustration of Editor's basics</description>
<change-notes>Initial commit</change-notes>
<!-- please see http://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description -->
<idea-version since-build="131"/>
<depends>com.intellij.modules.lang</depends>
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
</extensions>
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
</project-components>
<actions>
<action id="EditorBasics.EditorIllustration" class="org.jetbrains.tutorials.editor.basics.EditorIllustration" text="Editor Basics"
description="Illustrates how to plug an action in">
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
</action>
<action id="EditorBasics.EditorHandlerIllustration" class="org.jetbrains.tutorials.editor.basics.EditorHandlerIllustration" text="Editor Handler"
description="Illustrates how to plug an action in">
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
</action>
<action id="EditorBasics.LogicalPositionIllustration" class="org.jetbrains.tutorials.editor.basics.EditorAreaIllustration" text="Caret Position"
description="Illustrates how editor area is organized">
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
</action>
</actions>
</idea-plugin>

View File

@ -0,0 +1,32 @@
package org.jetbrains.tutorials.editor.basics;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
/**
* @author Anna Bulenkova
*/
public class EditorAreaIllustration extends AnAction {
@Override
public void actionPerformed(AnActionEvent anActionEvent) {
final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR);
CaretModel caretModel = editor.getCaretModel();
LogicalPosition logicalPosition = caretModel.getLogicalPosition();
VisualPosition visualPosition = caretModel.getVisualPosition();
int offset = caretModel.getOffset();
Messages.showInfoMessage(logicalPosition.toString() + "\n" +
visualPosition.toString() + "\n" +
"Offset: " + offset, "Caret Parameters Inside The Editor");
}
@Override
public void update(AnActionEvent e) {
final Project project = e.getData(CommonDataKeys.PROJECT);
final Editor editor = e.getData(CommonDataKeys.EDITOR);
e.getPresentation().setVisible(project != null && editor != null);
}
}

View File

@ -0,0 +1,32 @@
package org.jetbrains.tutorials.editor.basics;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class EditorHandlerIllustration extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR);
EditorActionManager actionManager = EditorActionManager.getInstance();
//Insert one more caret below the active caret
EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW);
actionHandler.execute(editor, editor.getCaretModel().getCurrentCaret(), anActionEvent.getDataContext());
}
@Override
public void update(@NotNull final AnActionEvent anActionEvent) {
//Set visible if at least one caret is available
final Project project = anActionEvent.getData(CommonDataKeys.PROJECT);
final Editor editor = anActionEvent.getData(CommonDataKeys.EDITOR);
anActionEvent.getPresentation().setVisible((project != null && editor != null && !editor.getCaretModel().getAllCarets().isEmpty()));
}
}

View File

@ -0,0 +1,55 @@
package org.jetbrains.tutorials.editor.basics;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actionSystem.TypedAction;
import com.intellij.openapi.project.Project;
/**
* @author Anna Bulenkova
*/
public class EditorIllustration extends AnAction {
static {
final EditorActionManager actionManager = EditorActionManager.getInstance();
final TypedAction typedAction = actionManager.getTypedAction();
typedAction.setupHandler(new MyTypedHandler());
}
@Override
public void actionPerformed(final AnActionEvent anActionEvent) {
//Get all the required data from data keys
final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR);
final Project project = anActionEvent.getRequiredData(CommonDataKeys.PROJECT);
//Access document, caret, and selection
final Document document = editor.getDocument();
final SelectionModel selectionModel = editor.getSelectionModel();
final int start = selectionModel.getSelectionStart();
final int end = selectionModel.getSelectionEnd();
//New instance of Runnable to make a replacement
Runnable runnable = new Runnable() {
@Override
public void run() {
document.replaceString(start, end, "Replacement");
}
};
//Making the replacement
WriteCommandAction.runWriteCommandAction(project, runnable);
selectionModel.removeSelection();
}
@Override
public void update(final AnActionEvent e) {
//Get required data keys
final Project project = e.getData(CommonDataKeys.PROJECT);
final Editor editor = e.getData(CommonDataKeys.EDITOR);
//Set visibility only in case of existing project and editor and if some text in the editor is selected
e.getPresentation().setVisible((project != null && editor != null && editor.getSelectionModel().hasSelection()));
}
}

View File

@ -0,0 +1,27 @@
package org.jetbrains.tutorials.editor.basics;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.TypedActionHandler;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class MyTypedHandler implements TypedActionHandler {
@Override
public void execute(@NotNull Editor editor, char c, @NotNull DataContext dataContext) {
final Document document = editor.getDocument();
Project project = editor.getProject();
Runnable runnable = new Runnable() {
@Override
public void run() {
document.insertString(0, "Typed\n");
}
};
WriteCommandAction.runWriteCommandAction(project, runnable);
}
}

View File

@ -0,0 +1,36 @@
<idea-plugin version="2">
<id>com.intellij.tutorials.facet</id>
<name>Facet Demo</name>
<version>1.0</version>
<vendor email="support@jrtbrains.com" url="http://www.yourcompany.com">JetBrains</vendor>
<description>Basic example of working with facets</description>
<change-notes>Initial commit</change-notes>
<!-- please see https://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description -->
<idea-version since-build="131"/>
<!-- please see https://confluence.jetbrains.com/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products
on how to target different products -->
<!-- uncomment to enable plugin in all products
<depends>com.intellij.modules.lang</depends>
-->
<extensions defaultExtensionNs="com.intellij">
<facetType implementation="com.intellij.tutorials.facet.DemoFacetType"/>
</extensions>
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
</project-components>
<actions>
<!-- Add your actions here -->
</actions>
</idea-plugin>

View File

@ -0,0 +1,16 @@
package com.intellij.tutorials.facet;
import com.intellij.facet.Facet;
import com.intellij.facet.FacetType;
import com.intellij.openapi.module.Module;
/**
* @author Anna Bulenkova
*/
public class DemoFacet extends Facet<DemoFacetConfiguration> {
public static final String ID = "DEMO_FACET_ID";
public DemoFacet(FacetType facetType, Module module, String name, DemoFacetConfiguration configuration, Facet underlyingFacet) {
super(facetType, module, name, configuration, underlyingFacet);
}
}

View File

@ -0,0 +1,79 @@
package com.intellij.tutorials.facet;
import com.intellij.facet.FacetConfiguration;
import com.intellij.facet.ui.FacetEditorContext;
import com.intellij.facet.ui.FacetEditorTab;
import com.intellij.facet.ui.FacetValidatorsManager;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import org.jdom.Element;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
/**
* @author Anna Bulenkova
*/
public class DemoFacetConfiguration implements FacetConfiguration {
public static final String DEMO_FACET_TAG_NAME = "DemoFacet";
public static final String PATH_TO_SDK_ATTR_NAME = "pathToSdk";
private String myPathToSdk = "";
JTextField myPath = new JTextField(myPathToSdk);
@Override
public FacetEditorTab[] createEditorTabs(FacetEditorContext context, FacetValidatorsManager manager) {
return new FacetEditorTab[] {
new FacetEditorTab() {
@NotNull
@Override
public JComponent createComponent() {
JPanel top = new JPanel(new BorderLayout());
top.add(new JLabel("Path to SDK: "), BorderLayout.WEST);
top.add(myPath);
JPanel panel = new JPanel(new BorderLayout());
panel.add(top, BorderLayout.NORTH);
return panel;
}
@Nls
@Override
public String getDisplayName() {
return "Demo Framework";
}
@Override
public boolean isModified() {
return myPath.getText().equalsIgnoreCase(myPathToSdk);
// return !StringUtil.equalsIgnoreWhitespaces(myPath.getText(), myPathToSdk);
}
@Override
public void reset() {
myPath.setText(myPathToSdk);
}
@Override
public void disposeUIResources() {
}
}
};
}
@Override
public void readExternal(Element element) throws InvalidDataException {
Element facet = element.getChild(DEMO_FACET_TAG_NAME);
if (facet != null) {
myPathToSdk = facet.getAttributeValue(PATH_TO_SDK_ATTR_NAME, "");
myPath.setText(myPathToSdk);
}
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
Element facet = new Element(DEMO_FACET_TAG_NAME);
facet.setAttribute(PATH_TO_SDK_ATTR_NAME, myPathToSdk);
element.addContent(facet);
}
}

View File

@ -0,0 +1,43 @@
package com.intellij.tutorials.facet;
import com.intellij.facet.Facet;
import com.intellij.facet.FacetType;
import com.intellij.facet.FacetTypeId;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/**
* @author Anna Bulenkova
*/
public class DemoFacetType extends FacetType<DemoFacet, DemoFacetConfiguration> {
private static final FacetTypeId<DemoFacet> TYPE_ID = new FacetTypeId<DemoFacet>(DemoFacet.ID);
public DemoFacetType() {
super(TYPE_ID, DemoFacet.ID, "Demo Facet");
}
@Override
public DemoFacetConfiguration createDefaultConfiguration() {
return new DemoFacetConfiguration();
}
@Override
public DemoFacet createFacet(@NotNull Module module, String s, @NotNull DemoFacetConfiguration configuration, Facet facet) {
return new DemoFacet(this, module, s, configuration, facet);
}
@Override
public boolean isSuitableModuleType(ModuleType type) {
return true;
}
@Nullable
@Override
public Icon getIcon() {
return AllIcons.General.Information;
}
}

View File

@ -0,0 +1,36 @@
<idea-plugin version="2">
<id>com.intellij.demo.framework</id>
<name>Framework example</name>
<version>1.0</version>
<vendor email="support@yourcompany.com" url="http://www.yourcompany.com">YourCompany</vendor>
<description>Framework support tutorial</description>
<change-notes>Initial commit</change-notes>
<!-- please see https://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description -->
<idea-version since-build="131"/>
<!-- please see https://confluence.jetbrains.com/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products
on how to target different products -->
<!-- uncomment to enable plugin in all products
<depends>com.intellij.modules.lang</depends>
-->
<extensions defaultExtensionNs="com.intellij">
<framework.type implementation="com.intellij.tutorials.framework.DemoFramework"/>
</extensions>
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
</project-components>
<actions>
<!-- Add your actions here -->
</actions>
</idea-plugin>

View File

@ -0,0 +1,71 @@
package com.intellij.tutorials.framework;
import com.intellij.framework.FrameworkTypeEx;
import com.intellij.framework.addSupport.FrameworkSupportInModuleConfigurable;
import com.intellij.framework.addSupport.FrameworkSupportInModuleProvider;
import com.intellij.icons.AllIcons;
import com.intellij.ide.util.frameworkSupport.FrameworkSupportModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.roots.ModifiableModelsProvider;
import com.intellij.openapi.roots.ModifiableRootModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/**
* @author Anna Bulenkova
*/
public class DemoFramework extends FrameworkTypeEx {
public static final String FRAMEWORK_ID = "Demo";
protected DemoFramework() {
super(FRAMEWORK_ID);
}
@NotNull
@Override
public FrameworkSupportInModuleProvider createProvider() {
return new FrameworkSupportInModuleProvider() {
@NotNull
@Override
public FrameworkTypeEx getFrameworkType() {
return DemoFramework.this;
}
@NotNull
@Override
public FrameworkSupportInModuleConfigurable createConfigurable(@NotNull FrameworkSupportModel model) {
return new FrameworkSupportInModuleConfigurable() {
@Nullable
@Override
public JComponent createComponent() {
return new JCheckBox("Extra Option");
}
@Override
public void addSupport(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ModifiableModelsProvider provider) {
//do what you want here: setup a library, generate a specific file, etc
}
};
}
@Override
public boolean isEnabledForModuleType(@NotNull ModuleType type) {
return true;
}
};
}
@NotNull
@Override
public String getPresentableName() {
return "Demo Framework";
}
@NotNull
@Override
public Icon getIcon() {
return AllIcons.Providers.Apache;
}
}

View File

@ -0,0 +1,31 @@
buildscript {
repositories {
mavenCentral()
}
}
plugins {
id "org.jetbrains.intellij" version "0.0.20"
}
apply plugin: 'idea'
apply plugin: 'org.jetbrains.intellij'
apply plugin: 'java'
compileJava {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
intellij {
version '15.0.1'
plugins 'coverage'
pluginName 'gradle_plugin_demo'
}
group 'org.jetbrains'
version '0.0.1-SNAPSHOT'
repositories {
mavenCentral ()
}

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Wed Nov 25 06:09:06 EST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-bin.zip

164
gradle_plugin_demo/gradlew vendored Normal file
View File

@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
gradle_plugin_demo/gradlew.bat vendored Normal file
View File

@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -0,0 +1,19 @@
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
/**
* Created by breandan on 11/25/2015.
*/
public class HelloAction extends AnAction {
public HelloAction() {
super("Hello");
}
public void actionPerformed(AnActionEvent event) {
Project project = event.getData(PlatformDataKeys.PROJECT);
Messages.showMessageDialog(project, "Hello world!", "Greeting", Messages.getInformationIcon());
}
}

View File

@ -0,0 +1,41 @@
<idea-plugin version="2">
<id>org.jetbrains</id>
<name>gradle_plugin_demo</name>
<version>0.0.1</version>
<vendor email="dummy" url="dummy">dummy</vendor>
<description><![CDATA[
Sample plugin.<br>
]]></description>
<change-notes><![CDATA[
Release 0.0.1: Initial release.<br>
]]>
</change-notes>
<!-- please see https://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description -->
<idea-version since-build="131"/>
<!-- please see https://confluence.jetbrains.com/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products
on how to target different products -->
<!-- uncomment to enable plugin in all products
<depends>com.intellij.modules.lang</depends>
-->
<extensions defaultExtensionNs="com.intellij">
</extensions>
<application-components>
</application-components>
<project-components>
</project-components>
<actions>
<group id="MyPlugin.SampleMenu" text="Greeting" description="Greeting menu">
<add-to-group group-id="MainMenu" anchor="last" />
<action id="Myplugin.Textboxes" class="HelloAction" text="Hello" description="Says hello" />
</group>
</actions>
</idea-plugin>

View File

@ -0,0 +1,30 @@
<idea-plugin version="2">
<id>com.intellij.tutorials.inspection</id>
<name>Inspection Demo</name>
<version>1.0</version>
<vendor email="support@jrtbrains.com" url="http://www.jetbrains.com">JetBrains</vendor>
<description>Basic example of working with code inspections</description>
<change-notes>Initial commit</change-notes>
<idea-version since-build="131"/>
<extensions defaultExtensionNs="com.intellij">
<inspectionToolProvider implementation="com.intellij.tutorials.inspection.DemoInspectionToolProvider"/>
</extensions>
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
</project-components>
<actions>
<!-- Add your actions here -->
</actions>
</idea-plugin>

View File

@ -0,0 +1,24 @@
package com.intellij.tutorials.inspection;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ProblemsHolder;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class DemoCodeInspection extends LocalInspectionTool {
@Nls
@NotNull
@Override
public String getDisplayName() {
return "Demo Inspection";
}
@NotNull
@Override
public DemoInspectionVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
return new DemoInspectionVisitor();
}
}

View File

@ -0,0 +1,12 @@
package com.intellij.tutorials.inspection;
import com.intellij.codeInspection.InspectionToolProvider;
/**
* @author Anna Bulenkova
*/
public class DemoInspectionToolProvider implements InspectionToolProvider {
public Class[] getInspectionClasses() {
return new Class[] { DemoCodeInspection.class};
}
}

View File

@ -0,0 +1,20 @@
package com.intellij.tutorials.inspection;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiPlainTextFile;
/**
* @author Anna Bulenkova
*/
public class DemoInspectionVisitor extends PsiElementVisitor {
@Override
public void visitElement(PsiElement element) {
super.visitElement(element);
}
@Override
public void visitPlainTextFile(PsiPlainTextFile file) {
super.visitPlainTextFile(file);
}
}

View File

@ -0,0 +1,7 @@
<html>
<body>
Write your description here.
<!-- tooltip end -->
Text after this comment will not be shown in tooltips.
</body>
</html>

View File

@ -0,0 +1,38 @@
<idea-plugin version="2">
<id>org.jetbrains</id>
<name>kotlin_demo</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>
<group id="MyPlugin.TestMeu" text="Greeting" description="Greeting menu">
<add-to-group group-id="MainMenu" anchor="last" />
<action id="Myplugin.Textboxes" class="HelloAction" text="Hello" description="Says hello" />
</group>
</actions>
</idea-plugin>

View File

@ -0,0 +1,12 @@
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.ui.Messages
//[Markdown reference](/tutorials/kotlin.md)
class HelloAction : AnAction("Hello") {
override fun actionPerformed(event: AnActionEvent) {
val project = event.getData(PlatformDataKeys.PROJECT)
Messages.showMessageDialog(project, "Hello from Kotlin!", "Greeting", Messages.getInformationIcon())
}
}

View File

@ -0,0 +1,37 @@
<idea-plugin version="2">
<id>live_templates</id>
<name>live_templates</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">
<defaultLiveTemplatesProvider implementation="MarkdownTemplateProvider"/>
<liveTemplateContext implementation="MarkdownContext"/>
</extensions>
<actions>
<!-- Add your actions here -->
</actions>
</idea-plugin>

View File

@ -0,0 +1,9 @@
<templateSet group="Markdown">
<template name="[" value="[$TEXT$]($LINK$)$END$" description="New link reference." toReformat="false" toShortenFQNames="false">
<variable name="TEXT" expression="" defaultValue="" alwaysStopAt="true" />
<variable name="LINK" expression="complete()" defaultValue="" alwaysStopAt="true" />
<context>
<option name="MARKDOWN" value="true" />
</context>
</template>
</templateSet>

View File

@ -0,0 +1,17 @@
import com.intellij.codeInsight.template.EverywhereContextType;
import com.intellij.codeInsight.template.TemplateContextType;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class MarkdownContext extends TemplateContextType {
protected MarkdownContext() {
super("MARKDOWN", "Markdown");
}
@Override
public boolean isInContext(@NotNull PsiFile file, int offset) {
return file.getName().endsWith(".md");
}
}

View File

@ -0,0 +1,16 @@
import com.intellij.codeInsight.template.impl.DefaultLiveTemplatesProvider;
import org.jetbrains.annotations.Nullable;
public class MarkdownTemplateProvider implements DefaultLiveTemplatesProvider {
@Override
public String[] getDefaultLiveTemplateFiles()
{
return new String[] {"liveTemplates/Markdown"};
}
@Nullable
@Override
public String[] getHiddenLiveTemplateFiles() {
return new String[0];
}
}

View File

@ -0,0 +1,29 @@
<idea-plugin version="2">
<name>max_opened_projects</name>
<description>short description of the plugin</description>
<version>1.0</version>
<vendor>YourCompany</vendor>
<idea-version since-build="8000"/>
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
<component>
<implementation-class>MyPackage.MaxProject</implementation-class>
</component>
</project-components>
<actions>
<!-- Add your actions here -->
</actions>
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<applicationService serviceInterface="MyPackage.MyCounter" serviceImplementation="MyPackage.MyCounter">
</applicationService>
</extensions>
</idea-plugin>

View File

@ -0,0 +1,54 @@
package MyPackage;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.Messages;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Chursin
* Date: Aug 13, 2010
* Time: 3:50:25 PM
* To change this template use File | Settings | File Templates.
*/
public class MaxProject implements ProjectComponent {
public MaxProject(Project project) {
}
public void initComponent() {
// TODO: insert component initialization logic here
}
public void disposeComponent() {
// TODO: insert component disposal logic here
}
@NotNull
public String getComponentName() {
return "MaxProject";
}
public void projectOpened() {
// called when project is opened
MyCounter CommandCounter = ServiceManager.getService(MyCounter.class);
if (CommandCounter.IncreaseCounter() == -1) {
Messages.showMessageDialog("The maximum number of opened projects exceeds " + String.valueOf(CommandCounter.MaxCount) +
" projects!", "Error", Messages.getErrorIcon());
ProjectManager PM=ProjectManager.getInstance();
Project[] AllProjects = PM.getOpenProjects();
Project project = AllProjects[AllProjects.length-1];
PM.closeProject(project);
}
}
public void projectClosed() {
// called when project is being closed
MyCounter CommandCounter = ServiceManager.getService(MyCounter.class);
CommandCounter.DecreaseCounter();
}
}

View File

@ -0,0 +1,29 @@
package MyPackage;
/**
* Created by IntelliJ IDEA.
* User: Alexey.Chursin
* Date: Aug 13, 2010
* Time: 3:49:33 PM
* To change this template use File | Settings | File Templates.
*/
public class MyCounter {
private int Count = 0;
// Sets the maximum allowed number of opened projects.
public final int MaxCount = 3;
public MyCounter(){
}
public int IncreaseCounter() {
Count++;
return (Count > MaxCount) ? -1:Count;
}
public int DecreaseCounter() {
Count--;
return (Count > MaxCount) ? -1:Count;
}
}

View File

@ -0,0 +1,36 @@
<idea-plugin version="2">
<id>com.intellij.tutorials.module</id>
<name>Module Type Demo</name>
<version>1.0</version>
<vendor email="support@jrtbrains.com" url="http://www.jetbrains.com">JetBrains</vendor>
<description>Basic example of working with module types</description>
<change-notes>Initial commit</change-notes>
<!-- please see https://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description -->
<idea-version since-build="131"/>
<!-- please see https://confluence.jetbrains.com/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products
on how to target different products -->
<!-- uncomment to enable plugin in all products
<depends>com.intellij.modules.lang</depends>
-->
<extensions defaultExtensionNs="com.intellij">
<moduleType id="DEMO_MODULE_TYPE" implementationClass="com.intellij.tutorials.module.DemoModuleType"/>
</extensions>
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
</project-components>
<actions>
<!-- Add your actions here -->
</actions>
</idea-plugin>

View File

@ -0,0 +1,31 @@
package com.intellij.tutorials.module;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.roots.ModifiableRootModel;
import org.jetbrains.annotations.Nullable;
/**
* @author Anna Bulenkova
*/
public class DemoModuleBuilder extends ModuleBuilder {
@Override
public void setupRootModel(ModifiableRootModel model) throws ConfigurationException {
}
@Override
public ModuleType getModuleType() {
return DemoModuleType.getInstance();
}
@Nullable
@Override
public ModuleWizardStep getCustomOptionsStep(WizardContext context, Disposable parentDisposable) {
return new DemoModuleWizardStep();
}
}

View File

@ -0,0 +1,60 @@
package com.intellij.tutorials.module;
import com.intellij.icons.AllIcons;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.ModuleTypeManager;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
/**
* @author Anna Bulenkova
*/
public class DemoModuleType extends ModuleType<DemoModuleBuilder> {
private static final String ID = "DEMO_MODULE_TYPE";
public DemoModuleType() {
super(ID);
}
public static DemoModuleType getInstance() {
return (DemoModuleType) ModuleTypeManager.getInstance().findByID(ID);
}
@NotNull
@Override
public DemoModuleBuilder createModuleBuilder() {
return new DemoModuleBuilder();
}
@NotNull
@Override
public String getName() {
return "Demo Module Type";
}
@NotNull
@Override
public String getDescription() {
return "Demo Module Type";
}
@Override
public Icon getBigIcon() {
return AllIcons.General.Information;
}
@Override
public Icon getNodeIcon(@Deprecated boolean b) {
return AllIcons.General.Information;
}
@NotNull
@Override
public ModuleWizardStep[] createWizardSteps(@NotNull WizardContext wizardContext, @NotNull DemoModuleBuilder moduleBuilder, @NotNull ModulesProvider modulesProvider) {
return super.createWizardSteps(wizardContext, moduleBuilder, modulesProvider);
}
}

View File

@ -0,0 +1,20 @@
package com.intellij.tutorials.module;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import javax.swing.*;
/**
* @author Anna Bulenkova
*/
public class DemoModuleWizardStep extends ModuleWizardStep {
@Override
public JComponent getComponent() {
return new JLabel("Provide some setting here");
}
@Override
public void updateDataModel() {
//todo update model according to UI
}
}

View File

@ -0,0 +1,140 @@
<idea-plugin version="2" url="www.jetbrains.com" use-idea-classloader="true">
<id>org.jetbrains.plugins.sample.PluginSample</id>
<name>Basic plugin example</name>
<version>1.0</version>
<vendor email="support@jetbrains.com" url="http://www.jetbrains.com">JetBrains</vendor>
<category>Samples</category>
<description><![CDATA[
Illustration of configuration options.<br>
<em>most HTML tags may be used</em>
]]></description>
<change-notes><![CDATA[
Initial release.<br>
<em>most HTML tags may be used</em>
]]>
</change-notes>
<!-- http://confluence.jetbrains.com/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products -->
<!-- The unique identifiers of the plugins on which this plugin depends -->
<!-- com.intellij.modules.lang is included in every IntelliJ-based IDE, plugin will be available as well -->
<depends>com.intellij.modules.lang</depends>
<!-- Optional dependency on another plugin. If the plugin with the "MySecondPlugin" ID is installed, the contents of mysecondplugin.xml (the format of this file conforms to the format of plugin.xml) will be loaded. -->
<!--<depends optional="true" config-file="custom-plugin.xml">CustomPlugin</depends>-->
<!-- Allows a plugin to integrate its help system (in JavaHelp format) with the IDEA help system. The "file" attribute specifies the name of the JAR file
in the "help" subdirectory of the plugin directory. The "path" attribute specifies the name of the helpset file within the JAR file.-->
<helpset file="plugin-help.jar" path="/Help.hs"/>
<!-- Minimum and maximum build of IDEA compatible with the plugin -->
<idea-version since-build="139.000" until-build="999"/>
<!-- Resource bundle from which the text of plugin descriptions, action names and etc. will be loaded -->
<resource-bundle>org.jetbrains.tutorials.sample.PluginSampleBundle</resource-bundle>
<!-- Plugin's application components -->
<application-components>
<component>
<!-- Component's interface class -->
<interface-class>org.jetbrains.tutorials.sample.DummyApplicationComponent</interface-class>
<!-- Component's implementation class -->
<implementation-class>org.jetbrains.tutorials.sample.DummyApplicationComponentImpl</implementation-class>
</component>
</application-components>
<!-- Plugin's project components -->
<project-components>
<component>
<!-- Interface and implementation classes are the same -->
<interface-class>org.jetbrains.tutorials.sample.DummyProjectComponent</interface-class>
<implementation-class>org.jetbrains.tutorials.sample.DummyProjectComponentImpl</implementation-class>
<!-- If the "workspace" option is set "true", the component saves its state to the .iws file
instead of the .ipr file. Note that the <option> element is used only if the component implements the JDOMExternalizable interface. Otherwise, the use of the <option> element takes no effect.-->
<option name="workspace" value="true"/>
<!-- If the "loadForDefaultProject" tag is present, the project component is instantiated also for the default project. -->
<loadForDefaultProject/>
</component>
</project-components>
<!-- Plugin's module components -->
<module-components>
<component>
<interface-class>org.jetbrains.tutorials.sample.DummyModuleComponent</interface-class>
<implementation-class>org.jetbrains.tutorials.sample.DummyModuleComponentImpl</implementation-class>
</component>
</module-components>
<!-- Actions -->
<actions>
<!-- The <action> element defines an action to register.
The mandatory "id" attribute specifies an unique identifier for the action.
The mandatory "class" attribute specifies the full-qualified name of the class implementing the action.
The mandatory "text" attribute specifies the text of the action (tooltip for toolbar button or text for menu item).
The optional "use-shortcut-of" attribute specifies the ID of the action whose keyboard shortcut this action will use.
The optional "description" attribute specifies the text which is displayed in the status bar when the action is focused.
The optional "icon" attribute specifies the icon which is displayed on the toolbar button or next to the menu item. -->
<action id="PluginSample.DummyAction" class="org.jetbrains.tutorials.sample.actions.SimpleAction" text="Dummy Action"
description="Illustrates how to plug an action in">
<!-- The <keyboard-shortcut> node specifies the keyboard shortcut for the action. An action can have several keyboard shortcuts.
The mandatory "first-keystroke" attribute specifies the first keystroke of the action. The key strokes are specified according to the regular Swing rules.
The optional "second-keystroke" attribute specifies the second keystroke of the action.
The mandatory "keymap" attribute specifies the keymap for which the action is active. IDs of the standard keymaps are defined as
constants in the com.intellij.openapi.keymap.KeymapManager class. -->
<keyboard-shortcut first-keystroke="control alt A" second-keystroke="C" keymap="$default"/>
<!-- The <mouse-shortcut> node specifies the mouse shortcut for the action. An action can have several mouse shortcuts.
The mandatory "keystroke" attribute specifies the clicks and modifiers for the action. It is defined as a sequence of words separated by spaces:
"button1", "button2", "button3" for the mouse buttons; "shift", "control", "meta", "alt", "altGraph" for the modifier keys;
"doubleClick" if the action is activated by a double-click of the button.
The mandatory "keymap" attribute specifies the keymap for which the action is active. IDs of the standard keymaps are defined as
constants in the com.intellij.openapi.keymap.KeymapManager class. -->
<mouse-shortcut keystroke="control button3 doubleClick" keymap="$default"/>
<!-- The <add-to-group> node specifies that the action should be added to an existing group. An action can be added to several groups.
The mandatory "group-id" attribute specifies the ID of the group to which the action is added.
The group must be implemented by an instance of the DefaultActionGroup class.
The mandatory "anchor" attribute specifies the position of the action in the group relative to other actions. It can have the values
"first", "last", "before" and "after".
The "relative-to-action" attribute is mandatory if the anchor is set to "before" and "after", and specifies the action before or after which
the current action is inserted. -->
<add-to-group group-id="ToolsMenu" anchor="after"/>
</action>
<!-- The <group> element defines an action group. <action>, <group> and <separator> elements defined within it are automatically included in the group.
The mandatory "id" attribute specifies an unique identifier for the action.
The optional "class" attribute specifies the full-qualified name of the class implementing the group. If not specified,
com.intellij.openapi.actionSystem.DefaultActionGroup is used.
The optional "text" attribute specifies the text of the group (text for the menu item showing the submenu).
The optional "description" attribute specifies the text which is displayed in the status bar when the group is focused.
The optional "icon" attribute specifies the icon which is displayed on the toolbar button or next to the group.
The optional "popup" attribute specifies how the group is presented in the menu. If a group has popup="true", actions in it
are placed in a submenu; for popup="false", actions are displayed as a section of the same menu delimited by separators. -->
<group id="DummyDefaultActionGroup" text="Default action group">
<action class="org.jetbrains.tutorials.sample.actions.GroupedToDefaultAction" id="PluginSample.GroupedToDefaultAction"/>
</group>
<group class="org.jetbrains.tutorials.sample.actions.DummyActionGroup" id="DummyActionGroup" text="Action Group"
description="Illustration of an action group"
icon="icons/testgroup.png" popup="true">
<action id="PluginSample.GroupedAction" class="org.jetbrains.tutorials.sample.actions.GroupedAction"
text="Grouped Action" description="An action in the group"/>
<!-- The <separator> element defines a separator between actions. It can also have an <add-to-group> child element. -->
<separator/>
<group id="ActionSubGroup"/>
<!-- The <reference> element allows to add an existing action to the group. The mandatory "ref" attribute specifies the ID of the action to add. -->
<reference ref="EditorCopy"/>
<add-to-group group-id="MainMenu" relative-to-action="HelpMenu" anchor="before"/>
</group>
</actions>
<!-- Extension points defined by the plugin. Extension points are registered by a plugin so that other plugins can provide this plugin
with certain data. The "beanClass" attribute specifies the class the implementations of which can be used for the extension point. -->
<!--<extensionPoints>-->
<!--<extensionPoint name="testExtensionPoint" beanClass="com.foo.impl.MyExtensionBean"/>-->
<!--</extensionPoints>-->
<!-- Extensions which the plugin adds to extension points defined by the IDEA core or by other plugins. The "defaultExtensionNs " attribute must be set to the ID of the plugin defining the extension point,
or to "com.intellij" if the extension point is defined by the IDEA core. The name of the
tag within the <extensions> tag matches the name of the extension point, and the "implementation" class specifies the name of the
class added to the extension point. -->
<extensions>
<!--<testExtensionPoint implementation="com.foo.impl.MyExtensionImpl"/>-->
</extensions>
</idea-plugin>

View File

@ -0,0 +1,9 @@
package org.jetbrains.tutorials.sample;
import com.intellij.openapi.components.ApplicationComponent;
/**
* @author Anna Bulenkova
*/
interface DummyApplicationComponent extends ApplicationComponent{
}

View File

@ -0,0 +1,24 @@
package org.jetbrains.tutorials.sample;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class DummyApplicationComponentImpl implements DummyApplicationComponent {
@Override
public void initComponent() {
}
@Override
public void disposeComponent() {
}
@NotNull
@Override
public String getComponentName() {
return "DummyApplicationComponent";
}
}

View File

@ -0,0 +1,9 @@
package org.jetbrains.tutorials.sample;
import com.intellij.openapi.module.ModuleComponent;
/**
* @author Anna Bulenkova
*/
public interface DummyModuleComponent extends ModuleComponent{
}

View File

@ -0,0 +1,39 @@
package org.jetbrains.tutorials.sample;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class DummyModuleComponentImpl implements DummyModuleComponent {
@Override
public void projectOpened() {
}
@Override
public void projectClosed() {
}
@Override
public void moduleAdded() {
}
@Override
public void initComponent() {
}
@Override
public void disposeComponent() {
}
@NotNull
@Override
public String getComponentName() {
return "DummyModuleComponent";
}
}

View File

@ -0,0 +1,9 @@
package org.jetbrains.tutorials.sample;
import com.intellij.openapi.components.ProjectComponent;
/**
* @author Anna Bulenkova
*/
public interface DummyProjectComponent extends ProjectComponent{
}

View File

@ -0,0 +1,34 @@
package org.jetbrains.tutorials.sample;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class DummyProjectComponentImpl implements DummyProjectComponent {
@Override
public void projectOpened() {
}
@Override
public void projectClosed() {
}
@Override
public void initComponent() {
}
@Override
public void disposeComponent() {
}
@NotNull
@Override
public String getComponentName() {
return "DummyProjectComponent";
}
}

View File

@ -0,0 +1,17 @@
package org.jetbrains.tutorials.sample.actions;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class DummyActionGroup extends ActionGroup {
@NotNull
@Override
public AnAction[] getChildren(AnActionEvent anActionEvent) {
return new GroupedAction[0];
}
}

View File

@ -0,0 +1,15 @@
package org.jetbrains.tutorials.sample.actions;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class GroupedAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
}
}

View File

@ -0,0 +1,15 @@
package org.jetbrains.tutorials.sample.actions;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class GroupedToDefaultAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
}
}

View File

@ -0,0 +1,24 @@
package org.jetbrains.tutorials.sample.actions;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class SimpleAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
}
@Override
public void update(@NotNull AnActionEvent e) {
//Make action visible and available only when project is defined
final Project project = e.getProject();
boolean isAvailable = project != null;
e.getPresentation().setVisible(isAvailable);
e.getPresentation().setEnabled(isAvailable);
}
}

View File

@ -0,0 +1,55 @@
<idea-plugin version="2" url="www.jetbrains.com">
<id>org.jetbrains.plugins.sample.ProjectModel</id>
<name>Editor basics</name>
<version>1.0</version>
<vendor email="support@jetbrains.com" url="http://www.jetbrains.com">JetBrains</vendor>
<description>Project model illustration</description>
<change-notes>Initial commit</change-notes>
<!-- please see http://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description -->
<idea-version since-build="131"/>
<depends>com.intellij.modules.lang</depends>
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
</extensions>
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
</project-components>
<actions>
<action id="ProjectModel.SourceRoots" class="com.intellij.tutorials.project.model.ShowSourceRootsActions"
text="Show Source Roots"
description="Illustrates how to get source roots">
<add-to-group group-id="ToolsMenu" anchor="after"/>
</action>
<action id="ProjectModel.ProjectSdk" class="com.intellij.tutorials.project.model.ProjectSdkAction"
text="Show Sdk Info"
description="Illustrates how to get source roots">
<add-to-group group-id="ToolsMenu" anchor="after"/>
</action>
<action id="ProjectModel.ProjectFileIndex"
class="com.intellij.tutorials.project.model.ProjectFileIndexSampleAction"
text="FileProjectIndex in Action"
description="Illustrates how to get source roots">
<add-to-group group-id="EditorPopupMenu" anchor="last"/>
</action>
<action id="ProjectModel.ModificationAction" class="com.intellij.tutorials.project.model.ModificationAction"
text="Project Modification in Action"
description="Illustrates how to get source roots">
<add-to-group group-id="EditorPopupMenu" anchor="last"/>
</action>
<action id="ProjectModel.LibrariesAction" class="com.intellij.tutorials.project.model.LibrariesAction"
text="Libraries for file"
description="Illustrates accessing libraries">
<add-to-group group-id="EditorPopupMenu" anchor="last"/>
</action>
</actions>
</idea-plugin>

View File

@ -0,0 +1,63 @@
package com.intellij.tutorials.project.model;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class LibrariesAction extends AnAction {
@Override
public void update(@NotNull final AnActionEvent event) {
Project project = event.getProject();
if (project == null) return;
Navigatable element = event.getData(CommonDataKeys.NAVIGATABLE);
if (element instanceof PsiClass) {
PsiFile psiFile = ((PsiClass) element).getContainingFile();
if (psiFile == null) return;
VirtualFile virtualFile = psiFile.getVirtualFile();
if (virtualFile == null) return;
event.getPresentation().setEnabledAndVisible(true);
}
}
@Override
public void actionPerformed(@NotNull AnActionEvent event) {
Project project = event.getProject();
if (project == null) return;
Navigatable element = event.getData(CommonDataKeys.NAVIGATABLE);
if (element instanceof PsiClass) {
PsiFile psiFile = ((PsiClass) element).getContainingFile();
if (psiFile == null) return;
VirtualFile virtualFile = psiFile.getVirtualFile();
if (virtualFile == null) return;
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
StringBuilder jars = new StringBuilder();
for (OrderEntry orderEntry : fileIndex.getOrderEntriesForFile(virtualFile)) {
if (orderEntry instanceof LibraryOrderEntry) {
final LibraryOrderEntry libraryEntry = (LibraryOrderEntry) orderEntry;
final Library library = libraryEntry.getLibrary();
if (library == null) continue;
VirtualFile[] files = library.getFiles(OrderRootType.CLASSES);
if (files.length == 0) continue;
for (VirtualFile jar : files) {
jars.append(jar.getName()).append(", ");
}
}
}
if (jars.length() > 0) {
Messages.showInfoMessage("Libraries for file " + virtualFile.getName() + ": " + jars.toString(), "Libraries Info");
}
}
}
}

View File

@ -0,0 +1,48 @@
package com.intellij.tutorials.project.model;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class ModificationAction extends AnAction {
@Override
public void actionPerformed(@NotNull final AnActionEvent event) {
Project project = event.getProject();
if (project == null) return;
Navigatable element = event.getData(CommonDataKeys.NAVIGATABLE);
if (element instanceof PsiClass) {
PsiFile file = ((PsiClass) element).getContainingFile();
if (file == null) return;
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null) return;
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
final Module module = fileIndex.getModuleForFile(virtualFile);
if (module == null) return;
if (!ModuleRootManager.getInstance(module).getFileIndex().isInContent(virtualFile)) {
ModuleRootModificationUtil.addModuleLibrary(module, virtualFile.getUrl());
}
}
}
@Override
public void update(@NotNull final AnActionEvent event) {
Project project = event.getProject();
Navigatable element = event.getData(CommonDataKeys.NAVIGATABLE);
event.getPresentation().setEnabledAndVisible(project != null && element != null);
}
}

View File

@ -0,0 +1,55 @@
package com.intellij.tutorials.project.model;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class ProjectFileIndexSampleAction extends AnAction {
@Override
public void update(@NotNull final AnActionEvent event) {
Project project = event.getProject();
final Editor editor = event.getData(CommonDataKeys.EDITOR);
boolean visibility = project != null && editor != null;
event.getPresentation().setEnabledAndVisible(visibility);
}
@Override
public void actionPerformed(@NotNull final AnActionEvent event) {
Project project = event.getProject();
final Editor editor = event.getData(CommonDataKeys.EDITOR);
if (project == null || editor == null) return;
Document document = editor.getDocument();
FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
VirtualFile virtualFile = fileDocumentManager.getFile(document);
ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
if (virtualFile != null) {
Module module = projectFileIndex.getModuleForFile(virtualFile);
String moduleName;
moduleName = module != null ? module.getName() : "No module defined for file";
VirtualFile moduleContentRoot = projectFileIndex.getContentRootForFile(virtualFile);
boolean isLibraryFile = projectFileIndex.isLibraryClassFile(virtualFile);
boolean isInLibraryClasses = projectFileIndex.isInLibraryClasses(virtualFile);
boolean isInLibrarySource = projectFileIndex.isInLibrarySource(virtualFile);
Messages.showInfoMessage("Module: " + moduleName + "\n" +
"Module content root: " + moduleContentRoot + "\n" +
"Is library file: " + isLibraryFile + "\n" +
"Is in library classes" + isInLibraryClasses +
"Is in library source" + isInLibrarySource,
"Main File Info for" + virtualFile.getName());
}
}
}

View File

@ -0,0 +1,34 @@
package com.intellij.tutorials.project.model;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.Messages;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class ProjectSdkAction extends AnAction {
@Override
public void actionPerformed(@NotNull final AnActionEvent event) {
Project project = event.getProject();
if (project != null) {
String projectSDKName = ProjectRootManager.getInstance(project).getProjectSdkName();
String newProjectSdkName = "New Sdk Name";
ProjectRootManager.getInstance(project).setProjectSdkName(newProjectSdkName);
Messages.showInfoMessage(projectSDKName + " has changed to " + newProjectSdkName, "Project Sdk Info");
}
}
@Override
public void update(@NotNull final AnActionEvent event) {
Project project = event.getProject();
if (project != null) {
Sdk sdk = ProjectRootManager.getInstance(project).getProjectSdk();
event.getPresentation().setEnabledAndVisible(sdk != null);
}
}
}

View File

@ -0,0 +1,34 @@
package com.intellij.tutorials.project.model;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class ShowSourceRootsActions extends AnAction {
@Override
public void actionPerformed(@NotNull final AnActionEvent event) {
Project project = event.getProject();
if (project == null) return;
String projectName = project.getName();
StringBuilder sourceRootsList = new StringBuilder();
VirtualFile[] vFiles = ProjectRootManager.getInstance(project).getContentSourceRoots();
for (VirtualFile file : vFiles) {
sourceRootsList.append(file.getUrl()).append("\n");
}
Messages.showInfoMessage("Source roots for the " + projectName + " plugin:\n" + sourceRootsList, "Project Properties");
}
@Override
public void update(@NotNull final AnActionEvent event) {
boolean visibility = event.getProject() != null;
event.getPresentation().setEnabled(visibility);
event.getPresentation().setVisible(visibility);
}
}

View File

@ -0,0 +1,30 @@
<idea-plugin version="2" url="www.jetbrains.com">
<id>org.jetbrains.plugins.sample.ProjectViewPane</id>
<name>Project View Pain Demo</name>
<version>1.0</version>
<vendor email="support@jetbrains.com" url="http://www.jetbrains.com">JetBrains</vendor>
<description>Project View Pain Demo</description>
<change-notes>Initial commit</change-notes>
<!-- please see http://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description -->
<idea-version since-build="131"/>
<depends>com.intellij.modules.lang</depends>
<extensions defaultExtensionNs="com.intellij">
<projectViewPane implementation="org.jetbrains.tutorials.view.pane.ImagesProjectViewPane"/>
</extensions>
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
</project-components>
<actions>
<!-- Add your actions here -->
</actions>
</idea-plugin>

View File

@ -0,0 +1,171 @@
package org.jetbrains.tutorials.view.pane;
import com.intellij.icons.AllIcons;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.projectView.impl.ProjectViewImpl;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileAdapter;
import com.intellij.openapi.vfs.VirtualFileEvent;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.util.Alarm;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.*;
/**
* @author Anna Bulenkova
*/
public class ImagesProjectNode extends AbstractTreeNode<VirtualFile> {
private static final Key<Set<VirtualFile>> IMAGES_PROJECT_DIRS = Key.create("images.files.or.directories");
public ImagesProjectNode(final Project project) {
super(project, project.getBaseDir());
scanImages(project);
subscribeToVFS(project);
}
public ImagesProjectNode(Project project, VirtualFile file) {
super(project, file);
}
private void scanImages(Project project) {
addAllByExt(project, "png");
addAllByExt(project, "jpg");
}
private void addAllByExt(Project project, String ext) {
final Set<VirtualFile> imagesFiles = getImagesFiles(project);
final VirtualFile projectDir = project.getBaseDir();
for (VirtualFile file : FilenameIndex.getAllFilesByExt(project, ext)) {
while (file != null && !file.equals(projectDir)) {
imagesFiles.add(file);
file = file.getParent();
}
}
}
@NotNull
private Set<VirtualFile> getImagesFiles(Project project) {
Set<VirtualFile> files = project.getUserData(IMAGES_PROJECT_DIRS);
if (files == null) {
files = new HashSet<VirtualFile>();
project.putUserData(IMAGES_PROJECT_DIRS, files);
}
return files;
}
@Override
protected VirtualFile getVirtualFile() {
return getValue();
}
@NotNull
@Override
public Collection<? extends AbstractTreeNode> getChildren() {
final List<VirtualFile> files = new ArrayList<VirtualFile>(0);
for (VirtualFile file : getValue().getChildren()) {
if (getImagesFiles(myProject).contains(file)) {
files.add(file);
}
}
if (files.isEmpty()) return Collections.emptyList();
final List<AbstractTreeNode> nodes = new ArrayList<AbstractTreeNode>(files.size());
final boolean alwaysOnTop = ((ProjectViewImpl) ProjectView.getInstance(myProject)).isFoldersAlwaysOnTop();
Collections.sort(files, new Comparator<VirtualFile>() {
@Override
public int compare(VirtualFile o1, VirtualFile o2) {
if (alwaysOnTop) {
final boolean d1 = o1.isDirectory();
final boolean d2 = o2.isDirectory();
if (d1 && !d2) return -1;
if (!d1 && d2) return 1;
}
return StringUtil.naturalCompare(o1.getName(), o2.getName());
}
});
for (VirtualFile file : files) {
nodes.add(new ImagesProjectNode(myProject, file));
}
return nodes;
}
@Override
protected void update(PresentationData data) {
data.setIcon(getValue().isDirectory() ? AllIcons.Nodes.Folder : getValue().getFileType().getIcon());
data.setPresentableText(getValue().getName());
}
@Override
public boolean canNavigate() {
return !getValue().isDirectory();
}
@Override
public boolean canNavigateToSource() {
return canNavigate();
}
@Override
public void navigate(boolean requestFocus) {
FileEditorManager.getInstance(myProject).openFile(getValue(), false);
}
private void subscribeToVFS(final Project project) {
final Alarm alarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, project);
LocalFileSystem.getInstance().addVirtualFileListener(new VirtualFileAdapter() {
{
final VirtualFileAdapter me = this;
Disposer.register(project, new Disposable() {
@Override
public void dispose() {
LocalFileSystem.getInstance().removeVirtualFileListener(me);
}
});
}
@Override
public void fileCreated(@NotNull VirtualFileEvent event) {
handle(event);
}
@Override
public void fileDeleted(@NotNull VirtualFileEvent event) {
handle(event);
}
void handle(VirtualFileEvent event) {
final String filename = event.getFileName().toLowerCase();
if (filename.endsWith(".png") || filename.endsWith(".jpg")) {
alarm.cancelAllRequests();
alarm.addRequest(new Runnable() {
public void run() {
getImagesFiles(project).clear();
scanImages(project);
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
ProjectView.getInstance(myProject).getProjectViewPaneById(ImagesProjectViewPane.ID).updateFromRoot(true);
}
});
}
}, 1000);
}
}
});
}
}

View File

@ -0,0 +1,109 @@
package org.jetbrains.tutorials.view.pane;
import com.intellij.icons.AllIcons;
import com.intellij.ide.SelectInTarget;
import com.intellij.ide.impl.ProjectViewSelectInTarget;
import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.projectView.impl.AbstractProjectViewPSIPane;
import com.intellij.ide.projectView.impl.ProjectAbstractTreeStructureBase;
import com.intellij.ide.projectView.impl.ProjectTreeStructure;
import com.intellij.ide.projectView.impl.ProjectViewTree;
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.ide.util.treeView.AbstractTreeUpdater;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
/**
* @author Anna Bulenkova
*/
public class ImagesProjectViewPane extends AbstractProjectViewPSIPane {
public static final String ID = "IMAGES";
protected ImagesProjectViewPane(Project project) {
super(project);
}
@Override
public String getTitle() {
return "Images";
}
@Override
public javax.swing.Icon getIcon() {
return AllIcons.FileTypes.Custom;
}
@NotNull
@Override
public String getId() {
return ID;
}
@Override
public int getWeight() {
return 10;
}
@Override
public SelectInTarget createSelectInTarget() {
return new ProjectViewSelectInTarget(myProject) {
@Override
public String toString() {
return "images";
}
@Nullable
@Override
public String getMinorViewId() {
return "images";
}
@Override
public float getWeight() {
return 10;
}
};
}
@Override
protected ProjectAbstractTreeStructureBase createStructure() {
return new ProjectTreeStructure(myProject, ID) {
@Override
protected AbstractTreeNode createRoot(Project project, ViewSettings settings) {
return new ImagesProjectNode(project);
}
@Override
public Object[] getChildElements(Object element) {
return super.getChildElements(element);
}
};
}
@Override
protected ProjectViewTree createTree(DefaultTreeModel model) {
return new ProjectViewTree(myProject, model) {
@Override
public DefaultMutableTreeNode getSelectedNode() {
return ImagesProjectViewPane.this.getSelectedNode();
}
@Override
public boolean isRootVisible() {
return true;
}
};
}
@Override
protected AbstractTreeUpdater createTreeUpdater(AbstractTreeBuilder builder) {
return new AbstractTreeUpdater(builder);
}
}

View File

@ -0,0 +1,31 @@
<idea-plugin version="2" url="www.jetbrains.com">
<id>org.jetbrains.tutorials.ProjectWizard</id>
<name>Project Wizard Demo</name>
<version>1.0</version>
<vendor email="support@jetbrains.com" url="http://www.jetbrains.com">JetBrains</vendor>
<description>Illustration of working with Project Wizard</description>
<change-notes>Initial commit</change-notes>
<!-- please see http://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description -->
<idea-version since-build="131"/>
<depends>com.intellij.modules.lang</depends>
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<moduleBuilder builderClass="org.jetbrains.tutorials.project.wizard.DemoModuleWizardStep" id="DEMO_STEP" order="first"/>
</extensions>
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
</project-components>
<actions>
</actions>
</idea-plugin>

View File

@ -0,0 +1,40 @@
package org.jetbrains.tutorials.project.wizard;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
/**
* @author Anna Bulenkova
*/
public class DemoModuleWizardStep extends ModuleBuilder {
public void setupRootModel(ModifiableRootModel modifiableRootModel) throws ConfigurationException {
}
public ModuleType getModuleType() {
return ModuleType.EMPTY; //or it could be other module type
}
@Override
public ModuleWizardStep[] createWizardSteps(@NotNull WizardContext wizardContext, @NotNull ModulesProvider modulesProvider) {
return new ModuleWizardStep[]{new ModuleWizardStep() {
@Override
public JComponent getComponent() {
return new JLabel("Put your content here");
}
@Override
public void updateDataModel() {
}
}};
}
}

View File

@ -0,0 +1,83 @@
<idea-plugin version="2">
<id>org.jetbrains.plugins.sample.RegisterActions</id>
<name>Sample plugin for working with IntelliJ Action System</name>
<version>1.0</version>
<vendor email="support@jetbrains.com" url="http://www.jetbrains.com">JetBrains</vendor>
<description>Illustration of Action System</description>
<change-notes>Initial commit</change-notes>
<!-- please see https://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description -->
<idea-version since-build="131"/>
<depends>com.intellij.modules.lang</depends>
<!-- please see https://confluence.jetbrains.com/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products
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>
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
</project-components>
<actions>
<!-- Add your actions here -->
<!-- The <action> element defines an action to register.
The mandatory "id" attribute specifies an unique identifier for the action.
The mandatory "class" attribute specifies the full-qualified name of the class implementing the action.
The mandatory "text" attribute specifies the text of the action (tooltip for toolbar button or text for menu item).
The optional "use-shortcut-of" attribute specifies the ID of the action whose keyboard shortcut this action will use.
The optional "description" attribute specifies the text which is displayed in the status bar when the action is focused.
The optional "icon" attribute specifies the icon which is displayed on the toolbar button or next to the menu item. -->
<action id="org.jetbrains.tutorials.actions.SimpleAction" class="org.jetbrains.tutorials.actions.SimpleAction"
text="Simple Action" description="IntelliJ Action System Demo">
<!-- The <keyboard-shortcut> node specifies the keyboard shortcut for the action. An action can have several keyboard shortcuts.
The mandatory "first-keystroke" attribute specifies the first keystroke of the action. The key strokes are specified according to the regular Swing rules.
The optional "second-keystroke" attribute specifies the second keystroke of the action.
The mandatory "keymap" attribute specifies the keymap for which the action is active. IDs of the standard keymaps are defined as
constants in the com.intellij.openapi.keymap.KeymapManager class. -->
<keyboard-shortcut first-keystroke="control alt A" second-keystroke="C" keymap="$default"/>
<!-- The <mouse-shortcut> node specifies the mouse shortcut for the action. An action can have several mouse shortcuts.
The mandatory "keystroke" attribute specifies the clicks and modifiers for the action. It is defined as a sequence of words separated by spaces:
"button1", "button2", "button3" for the mouse buttons; "shift", "control", "meta", "alt", "altGraph" for the modifier keys;
"doubleClick" if the action is activated by a double-click of the button.
The mandatory "keymap" attribute specifies the keymap for which the action is active. IDs of the standard keymaps are defined as
constants in the com.intellij.openapi.keymap.KeymapManager class. -->
<mouse-shortcut keystroke="control button3 doubleClick" keymap="$default"/>
<!-- The <add-to-group> node specifies that the action should be added to an existing group. An action can be added to several groups.
The mandatory "group-id" attribute specifies the ID of the group to which the action is added.
The group must be implemented by an instance of the DefaultActionGroup class.
The mandatory "anchor" attribute specifies the position of the action in the group relative to other actions. It can have the values
"first", "last", "before" and "after".
The "relative-to-action" attribute is mandatory if the anchor is set to "before" and "after", and specifies the action before or after which
the current action is inserted. -->
<add-to-group group-id="ToolsMenu" anchor="first"/>
</action>
<group id="SimpleGroup" text="Custom Action Group" popup="true">
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
<action class="org.jetbrains.tutorials.actions.GroupedAction" id="org.jetbrains.tutorials.actions.GroupedAction"
text="Grouped Action" description="Grouped Action Demo">
</action>
</group>
<group id="CustomDefaultActionGroup" class="org.jetbrains.tutorials.actions.CustomDefaultActionGroup" popup="true"
text="DefaultActionGroup Inheritor" description="Default Action Group Demo">
<add-to-group group-id="ToolsMenu" anchor="last"/>
<action class="org.jetbrains.tutorials.actions.CustomGroupedAction" id="CustomGroupedAction"
text="Custom Grouped Action" description="Custom Grouped Action Demo"/>
</group>
<group id="BaseActionGroup" class="org.jetbrains.tutorials.actions.BaseActionGroup" popup="true"
text="ActionGroup Demo" description="Extending AnAction Demo">
<add-to-group group-id="ToolsMenu" anchor="first"/>
</group>
</actions>
</idea-plugin>

View File

@ -0,0 +1,26 @@
package org.jetbrains.tutorials.actions;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import org.jetbrains.annotations.NotNull;
/**
* @author Anna Bulenkova
*/
public class BaseActionGroup extends ActionGroup {
@NotNull
@Override
public AnAction[] getChildren(AnActionEvent anActionEvent) {
return new AnAction[]{new MyAction()};
}
class MyAction extends AnAction {
public MyAction() {
super("Dynamically Added Action");
}
@Override
public void actionPerformed(@NotNull AnActionEvent anActionEvent) {
//does nothing
}
}
}

View File

@ -0,0 +1,20 @@
package org.jetbrains.tutorials.actions;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.editor.Editor;
/**
* @author Anna Bulenkova
*/
public class CustomDefaultActionGroup extends DefaultActionGroup {
@Override
public void update(AnActionEvent event) {
Editor editor = event.getData(CommonDataKeys.EDITOR);
event.getPresentation().setVisible(true);
event.getPresentation().setEnabled(editor != null);
event.getPresentation().setIcon(AllIcons.General.Error);
}
}

View File

@ -0,0 +1,14 @@
package org.jetbrains.tutorials.actions;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
/**
* @author Anna Bulenkova
*/
public class CustomGroupedAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent anActionEvent) {
//Does nothing
}
}

View File

@ -0,0 +1,19 @@
package org.jetbrains.tutorials.actions;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
/**
* @author Anna Bulenkova
*/
public class GroupedAction extends AnAction {
@Override
public void update(AnActionEvent event) {
event.getPresentation().setEnabledAndVisible(true);
}
@Override
public void actionPerformed(AnActionEvent event) {
//Does nothing
}
}

View File

@ -0,0 +1,29 @@
package org.jetbrains.tutorials.actions;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
/**
* @author Anna Bulenkova
*/
public class SimpleAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent anActionEvent) {
Object navigatable = anActionEvent.getData(CommonDataKeys.NAVIGATABLE);
if (navigatable != null) {
Messages.showDialog(navigatable.toString(), "Selected Element:", new String[]{"OK"}, -1, null);
}
}
@Override
public void update(AnActionEvent anActionEvent) {
final Project project = anActionEvent.getData(CommonDataKeys.PROJECT);
if (project != null)
return;
Object navigatable = anActionEvent.getData(CommonDataKeys.NAVIGATABLE);
anActionEvent.getPresentation().setVisible(navigatable != null);
}
}

View File

@ -0,0 +1,30 @@
<idea-plugin version="2" url="www.jetbrains.com">
<id>org.jetbrains.tutorials.run.configuration</id>
<name>Run Configuration</name>
<version>1.0</version>
<vendor email="support@jetbrains.com" url="http://www.jetbrains.com">JetBrains</vendor>
<description>Illustration of working with run configurations</description>
<change-notes>Initial commit</change-notes>
<!-- please see http://confluence.jetbrains.com/display/IDEADEV/Build+Number+Ranges for description -->
<idea-version since-build="131"/>
<depends>com.intellij.modules.lang</depends>
<extensions defaultExtensionNs="com.intellij">
<configurationType implementation="org.jetbrains.tutorials.run.configuration.DemoRunConfigurationType"/>
</extensions>
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
</project-components>
<actions>
</actions>
</idea-plugin>

View File

@ -0,0 +1,27 @@
package org.jetbrains.tutorials.run.configuration;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.openapi.project.Project;
/**
* @author Anna Bulenkova
*/
public class DemoConfigurationFactory extends ConfigurationFactory {
private static final String FACTORY_NAME = "Demo configuration factory";
protected DemoConfigurationFactory(ConfigurationType type) {
super(type);
}
@Override
public RunConfiguration createTemplateConfiguration(Project project) {
return new DemoRunConfiguration(project, this, "Demo");
}
@Override
public String getName() {
return FACTORY_NAME;
}
}

View File

@ -0,0 +1,36 @@
package org.jetbrains.tutorials.run.configuration;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.*;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Anna Bulenkova
*/
public class DemoRunConfiguration extends RunConfigurationBase {
protected DemoRunConfiguration(Project project, ConfigurationFactory factory, String name) {
super(project, factory, name);
}
@NotNull
@Override
public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
return new DemoSettingsEditor();
}
@Override
public void checkConfiguration() throws RuntimeConfigurationException {
}
@Nullable
@Override
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment executionEnvironment) throws ExecutionException {
return null;
}
}

View File

@ -0,0 +1,39 @@
package org.jetbrains.tutorials.run.configuration;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.icons.AllIcons;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
/**
* @author Anna Bulenkova
*/
public class DemoRunConfigurationType implements ConfigurationType {
@Override
public String getDisplayName() {
return "Demo";
}
@Override
public String getConfigurationTypeDescription() {
return "Demo Run Configuration Type";
}
@Override
public Icon getIcon() {
return AllIcons.General.Information;
}
@NotNull
@Override
public String getId() {
return "DEMO_RUN_CONFIGURATION";
}
@Override
public ConfigurationFactory[] getConfigurationFactories() {
return new ConfigurationFactory[]{new DemoConfigurationFactory(this)};
}
}

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.tutorials.run.configuration.DemoSettingsEditor">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="57eab" class="com.intellij.openapi.ui.LabeledComponent" binding="myMainClass" custom-create="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="-1" height="20"/>
</grid>
</constraints>
<properties>
<labelLocation value="West"/>
<text value="Script file"/>
</properties>
</component>
<vspacer id="93bd6">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
</form>

View File

@ -0,0 +1,44 @@
package org.jetbrains.tutorials.run.configuration;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.ui.ComponentWithBrowseButton;
import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
/**
* @author Anna Bulenkova
*/
/**
* @author Anna Bulenkova
*/
public class DemoSettingsEditor extends SettingsEditor<DemoRunConfiguration> {
private JPanel myPanel;
private LabeledComponent<ComponentWithBrowseButton> myMainClass;
@Override
protected void resetEditorFrom(DemoRunConfiguration demoRunConfiguration) {
}
@Override
protected void applyEditorTo(DemoRunConfiguration demoRunConfiguration) throws ConfigurationException {
}
@NotNull
@Override
protected JComponent createEditor() {
return myPanel;
}
private void createUIComponents() {
myMainClass = new LabeledComponent<ComponentWithBrowseButton>();
myMainClass.setComponent(new TextFieldWithBrowseButton());
}
}

Binary file not shown.

View File

@ -0,0 +1,104 @@
// This is a generated file. Not intended for manual editing.
package com.simpleplugin.parser;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiBuilder.Marker;
import static com.simpleplugin.psi.SimpleTypes.*;
import static com.intellij.lang.parser.GeneratedParserUtilBase.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.lang.ASTNode;
import com.intellij.psi.tree.TokenSet;
import com.intellij.lang.PsiParser;
import com.intellij.lang.LightPsiParser;
@SuppressWarnings({"SimplifiableIfStatement", "UnusedAssignment"})
public class SimpleParser implements PsiParser, LightPsiParser {
public ASTNode parse(IElementType t, PsiBuilder b) {
parseLight(t, b);
return b.getTreeBuilt();
}
public void parseLight(IElementType t, PsiBuilder b) {
boolean r;
b = adapt_builder_(t, b, this, null);
Marker m = enter_section_(b, 0, _COLLAPSE_, null);
if (t == PROPERTY) {
r = property(b, 0);
}
else {
r = parse_root_(t, b, 0);
}
exit_section_(b, 0, m, t, r, true, TRUE_CONDITION);
}
protected boolean parse_root_(IElementType t, PsiBuilder b, int l) {
return simpleFile(b, l + 1);
}
/* ********************************************************** */
// property|COMMENT|CRLF
static boolean item_(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "item_")) return false;
boolean r;
Marker m = enter_section_(b);
r = property(b, l + 1);
if (!r) r = consumeToken(b, COMMENT);
if (!r) r = consumeToken(b, CRLF);
exit_section_(b, m, null, r);
return r;
}
/* ********************************************************** */
// (KEY? SEPARATOR VALUE?) | KEY
public static boolean property(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "property")) return false;
if (!nextTokenIs(b, "<property>", KEY, SEPARATOR)) return false;
boolean r;
Marker m = enter_section_(b, l, _NONE_, "<property>");
r = property_0(b, l + 1);
if (!r) r = consumeToken(b, KEY);
exit_section_(b, l, m, PROPERTY, r, false, null);
return r;
}
// KEY? SEPARATOR VALUE?
private static boolean property_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "property_0")) return false;
boolean r;
Marker m = enter_section_(b);
r = property_0_0(b, l + 1);
r = r && consumeToken(b, SEPARATOR);
r = r && property_0_2(b, l + 1);
exit_section_(b, m, null, r);
return r;
}
// KEY?
private static boolean property_0_0(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "property_0_0")) return false;
consumeToken(b, KEY);
return true;
}
// VALUE?
private static boolean property_0_2(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "property_0_2")) return false;
consumeToken(b, VALUE);
return true;
}
/* ********************************************************** */
// item_*
static boolean simpleFile(PsiBuilder b, int l) {
if (!recursion_guard_(b, l, "simpleFile")) return false;
int c = current_position_(b);
while (true) {
if (!item_(b, l + 1)) break;
if (!empty_element_parsed_guard_(b, "simpleFile", c)) break;
c = current_position_(b);
}
return true;
}
}

View File

@ -0,0 +1,23 @@
// This is a generated file. Not intended for manual editing.
package com.simpleplugin.psi;
import java.util.List;
import org.jetbrains.annotations.*;
import com.intellij.psi.PsiElement;
import com.intellij.navigation.ItemPresentation;
public interface SimpleProperty extends SimpleNamedElement {
String getKey();
String getValue();
String getName();
PsiElement setName(String newName);
PsiElement getNameIdentifier();
ItemPresentation getPresentation();
}

View File

@ -0,0 +1,28 @@
// This is a generated file. Not intended for manual editing.
package com.simpleplugin.psi;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.PsiElement;
import com.intellij.lang.ASTNode;
import com.simpleplugin.psi.impl.*;
public interface SimpleTypes {
IElementType PROPERTY = new SimpleElementType("PROPERTY");
IElementType COMMENT = new SimpleTokenType("COMMENT");
IElementType CRLF = new SimpleTokenType("CRLF");
IElementType KEY = new SimpleTokenType("KEY");
IElementType SEPARATOR = new SimpleTokenType("SEPARATOR");
IElementType VALUE = new SimpleTokenType("VALUE");
class Factory {
public static PsiElement createElement(ASTNode node) {
IElementType type = node.getElementType();
if (type == PROPERTY) {
return new SimplePropertyImpl(node);
}
throw new AssertionError("Unknown element type: " + type);
}
}
}

View File

@ -0,0 +1,22 @@
// This is a generated file. Not intended for manual editing.
package com.simpleplugin.psi;
import org.jetbrains.annotations.*;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiElement;
public class SimpleVisitor extends PsiElementVisitor {
public void visitProperty(@NotNull SimpleProperty o) {
visitNamedElement(o);
}
public void visitNamedElement(@NotNull SimpleNamedElement o) {
visitPsiElement(o);
}
public void visitPsiElement(@NotNull PsiElement o) {
visitElement(o);
}
}

View File

@ -0,0 +1,49 @@
// This is a generated file. Not intended for manual editing.
package com.simpleplugin.psi.impl;
import java.util.List;
import org.jetbrains.annotations.*;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import static com.simpleplugin.psi.SimpleTypes.*;
import com.simpleplugin.psi.*;
import com.intellij.navigation.ItemPresentation;
public class SimplePropertyImpl extends SimpleNamedElementImpl implements SimpleProperty {
public SimplePropertyImpl(ASTNode node) {
super(node);
}
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof SimpleVisitor) ((SimpleVisitor)visitor).visitProperty(this);
else super.accept(visitor);
}
public String getKey() {
return SimplePsiImplUtil.getKey(this);
}
public String getValue() {
return SimplePsiImplUtil.getValue(this);
}
public String getName() {
return SimplePsiImplUtil.getName(this);
}
public PsiElement setName(String newName) {
return SimplePsiImplUtil.setName(this, newName);
}
public PsiElement getNameIdentifier() {
return SimplePsiImplUtil.getNameIdentifier(this);
}
public ItemPresentation getPresentation() {
return SimplePsiImplUtil.getPresentation(this);
}
}

View File

@ -0,0 +1,251 @@
/** initial size of the lookahead buffer */
--- private static final int ZZ_BUFFERSIZE = ...;
/** lexical states */
--- lexical states, charmap
/* error codes */
private static final int ZZ_UNKNOWN_ERROR = 0;
private static final int ZZ_NO_MATCH = 1;
private static final int ZZ_PUSHBACK_2BIG = 2;
private static final char[] EMPTY_BUFFER = new char[0];
private static final int YYEOF = -1;
private static java.io.Reader zzReader = null; // Fake
/* error messages for the codes above */
private static final String ZZ_ERROR_MSG[] = {
"Unkown internal scanner error",
"Error: could not match input",
"Error: pushback value was too large"
};
--- isFinal list
/** the current state of the DFA */
private int zzState;
/** the current lexical state */
private int zzLexicalState = YYINITIAL;
/** this buffer contains the current text to be matched and is
the source of the yytext() string */
private CharSequence zzBuffer = "";
/** this buffer may contains the current text array to be matched when it is cheap to acquire it */
private char[] zzBufferArray;
/** the textposition at the last accepting state */
private int zzMarkedPos;
/** the textposition at the last state to be included in yytext */
private int zzPushbackPos;
/** the current text position in the buffer */
private int zzCurrentPos;
/** startRead marks the beginning of the yytext() string in the buffer */
private int zzStartRead;
/** endRead marks the last character in the buffer, that has been read
from input */
private int zzEndRead;
/**
* zzAtBOL == true <=> the scanner is currently at the beginning of a line
*/
private boolean zzAtBOL = true;
/** zzAtEOF == true <=> the scanner is at the EOF */
private boolean zzAtEOF;
--- user class code
--- constructor declaration
public final int getTokenStart(){
return zzStartRead;
}
public final int getTokenEnd(){
return getTokenStart() + yylength();
}
public void reset(CharSequence buffer, int start, int end,int initialState){
zzBuffer = buffer;
zzBufferArray = com.intellij.util.text.CharArrayUtil.fromSequenceWithoutCopying(buffer);
zzCurrentPos = zzMarkedPos = zzStartRead = start;
zzPushbackPos = 0;
zzAtEOF = false;
zzAtBOL = true;
zzEndRead = end;
yybegin(initialState);
}
/**
* Refills the input buffer.
*
* @return <code>false</code>, iff there was new input.
*
* @exception java.io.IOException if any I/O-Error occurs
*/
private boolean zzRefill() throws java.io.IOException {
return true;
}
/**
* Returns the current lexical state.
*/
public final int yystate() {
return zzLexicalState;
}
/**
* Enters a new lexical state
*
* @param newState the new lexical state
*/
public final void yybegin(int newState) {
zzLexicalState = newState;
}
/**
* Returns the text matched by the current regular expression.
*/
public final CharSequence yytext() {
return zzBuffer.subSequence(zzStartRead, zzMarkedPos);
}
/**
* Returns the character at position <tt>pos</tt> from the
* matched text.
*
* It is equivalent to yytext().charAt(pos), but faster
*
* @param pos the position of the character to fetch.
* A value from 0 to yylength()-1.
*
* @return the character at position pos
*/
public final char yycharat(int pos) {
return zzBufferArray != null ? zzBufferArray[zzStartRead+pos]:zzBuffer.charAt(zzStartRead+pos);
}
/**
* Returns the length of the matched text region.
*/
public final int yylength() {
return zzMarkedPos-zzStartRead;
}
/**
* Reports an error that occured while scanning.
*
* In a wellformed scanner (no or only correct usage of
* yypushback(int) and a match-all fallback rule) this method
* will only be called with things that "Can't Possibly Happen".
* If this method is called, something is seriously wrong
* (e.g. a JFlex bug producing a faulty scanner etc.).
*
* Usual syntax/scanner level error handling should be done
* in error fallback rules.
*
* @param errorCode the code of the errormessage to display
*/
--- zzScanError declaration
String message;
try {
message = ZZ_ERROR_MSG[errorCode];
}
catch (ArrayIndexOutOfBoundsException e) {
message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
}
--- throws clause
}
/**
* Pushes the specified amount of characters back into the input stream.
*
* They will be read again by then next call of the scanning method
*
* @param number the number of characters to be read again.
* This number must not be greater than yylength()!
*/
--- yypushback decl (contains zzScanError exception)
if ( number > yylength() )
zzScanError(ZZ_PUSHBACK_2BIG);
zzMarkedPos -= number;
}
--- zzDoEOF
/**
* Resumes scanning until the next regular expression is matched,
* the end of input is encountered or an I/O-Error occurs.
*
* @return the next token
* @exception java.io.IOException if any I/O-Error occurs
*/
--- yylex declaration
int zzInput;
int zzAction;
// cached fields:
int zzCurrentPosL;
int zzMarkedPosL;
int zzEndReadL = zzEndRead;
CharSequence zzBufferL = zzBuffer;
char[] zzBufferArrayL = zzBufferArray;
char [] zzCMapL = ZZ_CMAP;
--- local declarations
while (true) {
zzMarkedPosL = zzMarkedPos;
--- start admin (line, char, col count)
zzAction = -1;
zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
--- start admin (lexstate etc)
zzForAction: {
while (true) {
--- next input, line, col, char count, next transition, isFinal action
zzAction = zzState;
zzMarkedPosL = zzCurrentPosL;
--- line count update
}
}
}
// store back cached position
zzMarkedPos = zzMarkedPosL;
--- char count update
--- actions
default:
if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
zzAtEOF = true;
--- eofvalue
}
else {
--- no match
}
}
}
}
--- main
}

View File

@ -0,0 +1,60 @@
<idea-plugin version="2">
<id>com.simpleplugin.unique.plugin.id</id>
<name>Simple</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>
<small>most HTML tags may be used</small>
]]></description>
<change-notes><![CDATA[
Add change notes here.<br>
<small>most HTML tags may be used</small>
]]>
</change-notes>
<!-- please see http://confluence.jetbrains.net/display/IDEADEV/Build+Number+Ranges for description -->
<idea-version since-build="107.105"/>
<!-- please see http://confluence.jetbrains.net/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products
on how to target different products -->
<!-- uncomment to enable plugin in all products
<depends>com.intellij.modules.lang</depends>
-->
<application-components>
<!-- Add your application components here -->
</application-components>
<project-components>
<!-- Add your project components here -->
</project-components>
<actions>
<!-- Add your actions here -->
</actions>
<extensions defaultExtensionNs="com.intellij">
<!-- Add your extensions here -->
<fileTypeFactory implementation="com.simpleplugin.SimpleFileTypeFactory"/>
<lang.parserDefinition language="Simple" implementationClass="com.simpleplugin.SimpleParserDefinition"/>
<lang.syntaxHighlighterFactory key="Simple" language="Simple" implementationClass="com.simpleplugin.SimpleSyntaxHighlighterFactory"/>
<colorSettingsPage implementation="com.simpleplugin.SimpleColorSettingsPage"/>
<annotator language="JAVA" implementationClass="com.simpleplugin.SimpleAnnotator"/>
<codeInsight.lineMarkerProvider language="JAVA" implementationClass="com.simpleplugin.SimpleLineMarkerProvider"/>
<completion.contributor language="Simple" implementationClass="com.simpleplugin.SimpleCompletionContributor"/>
<psi.referenceContributor implementation="com.simpleplugin.SimpleReferenceContributor"/>
<lang.findUsagesProvider language="Simple" implementationClass="com.simpleplugin.SimpleFindUsagesProvider"/>
<lang.refactoringSupport language="Simple" implementationClass="com.simpleplugin.SimpleRefactoringSupportProvider"/>
<lang.foldingBuilder language="JAVA" implementationClass="com.simpleplugin.SimpleFoldingBuilder"/>
<gotoSymbolContributor implementation="com.simpleplugin.SimpleChooseByNameContributor"/>
<lang.psiStructureViewFactory language="Simple" implementationClass="com.simpleplugin.SimpleStructureViewFactory"/>
<lang.formatter language="Simple" implementationClass="com.simpleplugin.SimpleFormattingModelBuilder"/>
<codeStyleSettingsProvider implementation="com.simpleplugin.SimpleCodeStyleSettingsProvider"/>
<langCodeStyleSettingsProvider implementation="com.simpleplugin.SimpleLanguageCodeStyleSettingsProvider"/>
<lang.commenter language="Simple" implementationClass="com.simpleplugin.SimpleCommenter"/>
<todoIndexer filetype="Simple file" implementationClass="com.simpleplugin.SimpleTodoIndexer"/>
</extensions>
</idea-plugin>

View File

@ -0,0 +1,99 @@
package com.simpleplugin;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.FileTypeIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.indexing.FileBasedIndex;
import com.simpleplugin.psi.SimpleElementFactory;
import com.simpleplugin.psi.SimpleFile;
import com.simpleplugin.psi.SimpleProperty;
import com.simpleplugin.psi.SimpleTypes;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
class CreatePropertyQuickFix extends BaseIntentionAction {
private String key;
CreatePropertyQuickFix(String key) {
this.key = key;
}
@NotNull
@Override
public String getText() {
return "Create property";
}
@NotNull
@Override
public String getFamilyName() {
return "Simple properties";
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
@Override
public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) throws IncorrectOperationException {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
Collection<VirtualFile> virtualFiles = FileBasedIndex.getInstance().getContainingFiles(FileTypeIndex.NAME, SimpleFileType.INSTANCE,
GlobalSearchScope.allScope(project));
if (virtualFiles.size() == 1) {
createProperty(project, virtualFiles.iterator().next());
} else {
final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFileDescriptor(SimpleFileType.INSTANCE);
descriptor.setRoots(project.getBaseDir());
final VirtualFile file = FileChooser.chooseFile(descriptor, project, null);
if (file != null) {
createProperty(project, file);
}
}
}
});
}
private void createProperty(final Project project, final VirtualFile file) {
new WriteCommandAction.Simple(project) {
@Override
public void run() {
SimpleFile simpleFile = (SimpleFile) PsiManager.getInstance(project).findFile(file);
ASTNode lastChildNode = simpleFile.getNode().getLastChildNode();
if (lastChildNode != null && !lastChildNode.getElementType().equals(SimpleTypes.CRLF)) {
simpleFile.getNode().addChild(SimpleElementFactory.createCRLF(project).getNode());
}
// IMPORTANT: change spaces to escaped spaces or the new node will only have the first word for the key
SimpleProperty property = SimpleElementFactory.createProperty(project, key.replaceAll(" ", "\\\\ "), "");
simpleFile.getNode().addChild(property.getNode());
((Navigatable) property.getLastChild().getNavigationElement()).navigate(true);
FileEditorManager.getInstance(project).getSelectedTextEditor().getCaretModel().
moveCaretRelatively(2, 0, false, false, false);
// almost the same thing but manipulating plain text of the document instead of PSI
// FileEditorManager.getInstance(project).openFile(file, true);
// final Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
// final Document document = editor.getDocument();
// document.insertString(document.getTextLength(), "\n" + key.replaceAll(" ", "\\\\ ") + " = ");
// editor.getCaretModel().getPrimaryCaret().moveToOffset(document.getTextLength());
}
}.execute();
}
}

View File

@ -0,0 +1,23 @@
{
parserClass="com.simpleplugin.parser.SimpleParser"
extends="com.intellij.extapi.psi.ASTWrapperPsiElement"
psiClassPrefix="Simple"
psiImplClassSuffix="Impl"
psiPackage="com.simpleplugin.psi"
psiImplPackage="com.simpleplugin.psi.impl"
elementTypeHolderClass="com.simpleplugin.psi.SimpleTypes"
elementTypeClass="com.simpleplugin.psi.SimpleElementType"
tokenTypeClass="com.simpleplugin.psi.SimpleTokenType"
psiImplUtilClass="com.simpleplugin.psi.impl.SimplePsiImplUtil"
}
simpleFile ::= item_*
private item_ ::= (property|COMMENT|CRLF)
property ::= (KEY? SEPARATOR VALUE?) | KEY {mixin="com.simpleplugin.psi.impl.SimpleNamedElementImpl"
implements="com.simpleplugin.psi.SimpleNamedElement" methods=[getKey getValue getName setName getNameIdentifier getPresentation]}

View File

@ -0,0 +1,46 @@
package com.simpleplugin;
import com.intellij.lexer.FlexLexer;
import com.intellij.psi.tree.IElementType;
import com.simpleplugin.psi.SimpleTypes;
import com.intellij.psi.TokenType;
%%
%class SimpleLexer
%implements FlexLexer
%unicode
%function advance
%type IElementType
%eof{ return;
%eof}
CRLF= \n|\r|\r\n
WHITE_SPACE=[\ \t\f]
FIRST_VALUE_CHARACTER=[^ \n\r\f\\] | "\\"{CRLF} | "\\".
VALUE_CHARACTER=[^\n\r\f\\] | "\\"{CRLF} | "\\".
END_OF_LINE_COMMENT=("#"|"!")[^\r\n]*
SEPARATOR=[:=]
KEY_CHARACTER=[^:=\ \n\r\t\f\\] | "\\ "
%state WAITING_VALUE
%%
<YYINITIAL> {END_OF_LINE_COMMENT} { yybegin(YYINITIAL); return SimpleTypes.COMMENT; }
<YYINITIAL> {KEY_CHARACTER}+ { yybegin(YYINITIAL); return SimpleTypes.KEY; }
<YYINITIAL> {SEPARATOR} { yybegin(WAITING_VALUE); return SimpleTypes.SEPARATOR; }
<WAITING_VALUE> {CRLF}({CRLF}|{WHITE_SPACE})+ { yybegin(YYINITIAL); return TokenType.WHITE_SPACE; }
<WAITING_VALUE> {WHITE_SPACE}+ { yybegin(WAITING_VALUE); return TokenType.WHITE_SPACE; }
<WAITING_VALUE> {FIRST_VALUE_CHARACTER}{VALUE_CHARACTER}* { yybegin(YYINITIAL); return SimpleTypes.VALUE; }
({CRLF}|{WHITE_SPACE})+ { yybegin(YYINITIAL); return TokenType.WHITE_SPACE; }
{WHITE_SPACE}+ { yybegin(YYINITIAL); return TokenType.WHITE_SPACE; }
. { return TokenType.BAD_CHARACTER; }

Some files were not shown because too many files have changed in this diff Show More