commit e2e94dadb4f8ec3e72080576b127f545e806fc86 Author: breandan considine Date: Thu Jan 14 19:38:06 2016 -0800 First build for GH pages diff --git a/comparing_references_inspection/source/META-INF/plugin.xml b/comparing_references_inspection/source/META-INF/plugin.xml new file mode 100644 index 000000000..36bf3d61f --- /dev/null +++ b/comparing_references_inspection/source/META-INF/plugin.xml @@ -0,0 +1,14 @@ + + Comparing References Inspection + Inspection for (probably) inappropriate use of equality relation operation. + 1.0 + JetBrains + + + + + + + diff --git a/comparing_references_inspection/source/com/intellij/codeInspection/ComparingReferencesInspection.java b/comparing_references_inspection/source/com/intellij/codeInspection/ComparingReferencesInspection.java new file mode 100644 index 000000000..941fc702c --- /dev/null +++ b/comparing_references_inspection/source/com/intellij/codeInspection/ComparingReferencesInspection.java @@ -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; + } +} diff --git a/comparing_references_inspection/source/com/intellij/codeInspection/ComparingReferencesProvider.java b/comparing_references_inspection/source/com/intellij/codeInspection/ComparingReferencesProvider.java new file mode 100644 index 000000000..37f091454 --- /dev/null +++ b/comparing_references_inspection/source/com/intellij/codeInspection/ComparingReferencesProvider.java @@ -0,0 +1,10 @@ +package com.intellij.codeInspection; + +/** + * @author max + */ +public class ComparingReferencesProvider implements InspectionToolProvider { + public Class[] getInspectionClasses() { + return new Class[] { ComparingReferencesInspection.class}; + } +} diff --git a/comparing_references_inspection/source/inspectionDescriptions/ComparingReferences.html b/comparing_references_inspection/source/inspectionDescriptions/ComparingReferences.html new file mode 100644 index 000000000..ca5f9d5ee --- /dev/null +++ b/comparing_references_inspection/source/inspectionDescriptions/ComparingReferences.html @@ -0,0 +1,7 @@ + + +This inspection reports when the '==' or '!=' operator was used between expressions of +reference types.
+In the text field below, specify the semicolon separated list of classes to be considered as suspicious. + + diff --git a/comparing_references_inspection/testData/before.after.java b/comparing_references_inspection/testData/before.after.java new file mode 100644 index 000000000..a3058effc --- /dev/null +++ b/comparing_references_inspection/testData/before.after.java @@ -0,0 +1,6 @@ +public class X { + public boolean compare2Strings(java.lang.String s1, java.lang.String s2) { + return (s1.equals(s2)); + } + +} \ No newline at end of file diff --git a/comparing_references_inspection/testData/before.java b/comparing_references_inspection/testData/before.java new file mode 100644 index 000000000..23095bcfa --- /dev/null +++ b/comparing_references_inspection/testData/before.java @@ -0,0 +1,6 @@ +public class X { + public boolean compare2Strings(java.lang.String s1, java.lang.String s2) { + return (s1 == s2); + } + +} \ No newline at end of file diff --git a/comparing_references_inspection/testData/before1.after.java b/comparing_references_inspection/testData/before1.after.java new file mode 100644 index 000000000..acedf90e0 --- /dev/null +++ b/comparing_references_inspection/testData/before1.after.java @@ -0,0 +1,6 @@ +public class X { +public boolean compare2Dates(java.util.Date dt1, java.util.Date dt2){ + return (!dt1.equals(dt2)); + } + +} \ No newline at end of file diff --git a/comparing_references_inspection/testData/before1.java b/comparing_references_inspection/testData/before1.java new file mode 100644 index 000000000..325c4ebf5 --- /dev/null +++ b/comparing_references_inspection/testData/before1.java @@ -0,0 +1,6 @@ +public class X { +public boolean compare2Dates(java.util.Date dt1, java.util.Date dt2){ + return (dt1 != dt2); + } + +} \ No newline at end of file diff --git a/comparing_references_inspection/testSource/testPlugin/TestThisPlugin.java b/comparing_references_inspection/testSource/testPlugin/TestThisPlugin.java new file mode 100644 index 000000000..bf3769c2a --- /dev/null +++ b/comparing_references_inspection/testSource/testPlugin/TestThisPlugin.java @@ -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 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 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()"); + } + +} diff --git a/conditional_operator_intention/META-INF/plugin.xml b/conditional_operator_intention/META-INF/plugin.xml new file mode 100644 index 000000000..17c55b92a --- /dev/null +++ b/conditional_operator_intention/META-INF/plugin.xml @@ -0,0 +1,27 @@ + + Conditional Operator Converter + ConditionalOperatorConverter + Intention action that suggests to convert a conditional operator into + 'if' block. + + 1.3 + JetBrains + + + + + com.intellij.codeInsight.intention.ConditionalOperatorConvertor + Conditional Operator + ConditionalOperatorConvertor + + + + + + + com.intellij.codeInsight.intention.ConditionalOperatorConvertor + + + diff --git a/conditional_operator_intention/source/META-INF/plugin.xml b/conditional_operator_intention/source/META-INF/plugin.xml new file mode 100644 index 000000000..68ae2627b --- /dev/null +++ b/conditional_operator_intention/source/META-INF/plugin.xml @@ -0,0 +1,35 @@ + + com.your.company.unique.plugin.id + Plugin display name here + 1.0 + YourCompany + + + most HTML tags may be used + ]]> + + + most HTML tags may be used + ]]> + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/conditional_operator_intention/source/com/intellij/codeInsight/intention/ConditionalOperatorConvertor.java b/conditional_operator_intention/source/com/intellij/codeInsight/intention/ConditionalOperatorConvertor.java new file mode 100644 index 000000000..ffee0ad54 --- /dev/null +++ b/conditional_operator_intention/source/com/intellij/codeInsight/intention/ConditionalOperatorConvertor.java @@ -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; + } +} diff --git a/conditional_operator_intention/source/intentionDescriptions/ConditionalOperatorConvertor/after.java.template b/conditional_operator_intention/source/intentionDescriptions/ConditionalOperatorConvertor/after.java.template new file mode 100644 index 000000000..9cf0cf2d2 --- /dev/null +++ b/conditional_operator_intention/source/intentionDescriptions/ConditionalOperatorConvertor/after.java.template @@ -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); + } +} diff --git a/conditional_operator_intention/source/intentionDescriptions/ConditionalOperatorConvertor/before.java.template b/conditional_operator_intention/source/intentionDescriptions/ConditionalOperatorConvertor/before.java.template new file mode 100644 index 000000000..ef611ed1c --- /dev/null +++ b/conditional_operator_intention/source/intentionDescriptions/ConditionalOperatorConvertor/before.java.template @@ -0,0 +1,6 @@ +public class X { + void f(boolean isMale) { + String title = isMale ? "Mr." : "Ms."; + System.out.println("title = " + title); + } +} \ No newline at end of file diff --git a/conditional_operator_intention/source/intentionDescriptions/ConditionalOperatorConvertor/description.html b/conditional_operator_intention/source/intentionDescriptions/ConditionalOperatorConvertor/description.html new file mode 100644 index 000000000..3d6efdd8d --- /dev/null +++ b/conditional_operator_intention/source/intentionDescriptions/ConditionalOperatorConvertor/description.html @@ -0,0 +1,5 @@ + + + This intention converts a ternary operator to a corresponding if statement.
+ + \ No newline at end of file diff --git a/conditional_operator_intention/testData/before.template.after.java b/conditional_operator_intention/testData/before.template.after.java new file mode 100644 index 000000000..6682628f7 --- /dev/null +++ b/conditional_operator_intention/testData/before.template.after.java @@ -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); + } +} \ No newline at end of file diff --git a/conditional_operator_intention/testData/before.template.java b/conditional_operator_intention/testData/before.template.java new file mode 100644 index 000000000..74107ea2d --- /dev/null +++ b/conditional_operator_intention/testData/before.template.java @@ -0,0 +1,6 @@ +public class X { + void f(boolean isMale) { + String title = isMale ? "Mr." : "Ms."; + System.out.println("title = " + title); + } +} \ No newline at end of file diff --git a/conditional_operator_intention/testSource/testPlugin/YourTest.java b/conditional_operator_intention/testSource/testPlugin/YourTest.java new file mode 100644 index 000000000..1b2114b71 --- /dev/null +++ b/conditional_operator_intention/testSource/testPlugin/YourTest.java @@ -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 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"); + } + +} diff --git a/editor_basics/resources/META-INF/plugin.xml b/editor_basics/resources/META-INF/plugin.xml new file mode 100644 index 000000000..b25400a7d --- /dev/null +++ b/editor_basics/resources/META-INF/plugin.xml @@ -0,0 +1,42 @@ + + org.jetbrains.plugins.sample.EditorBasics + Editor basics + 1.0 + JetBrains + + Illustration of Editor's basics + + Initial commit + + + + com.intellij.modules.lang + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/editor_basics/src/org/jetbrains/tutorials/editor/basics/EditorAreaIllustration.java b/editor_basics/src/org/jetbrains/tutorials/editor/basics/EditorAreaIllustration.java new file mode 100644 index 000000000..f8efe3eaf --- /dev/null +++ b/editor_basics/src/org/jetbrains/tutorials/editor/basics/EditorAreaIllustration.java @@ -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); + } +} diff --git a/editor_basics/src/org/jetbrains/tutorials/editor/basics/EditorHandlerIllustration.java b/editor_basics/src/org/jetbrains/tutorials/editor/basics/EditorHandlerIllustration.java new file mode 100644 index 000000000..5232bb09a --- /dev/null +++ b/editor_basics/src/org/jetbrains/tutorials/editor/basics/EditorHandlerIllustration.java @@ -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())); + } +} diff --git a/editor_basics/src/org/jetbrains/tutorials/editor/basics/EditorIllustration.java b/editor_basics/src/org/jetbrains/tutorials/editor/basics/EditorIllustration.java new file mode 100644 index 000000000..8185cd324 --- /dev/null +++ b/editor_basics/src/org/jetbrains/tutorials/editor/basics/EditorIllustration.java @@ -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())); + } +} diff --git a/editor_basics/src/org/jetbrains/tutorials/editor/basics/MyTypedHandler.java b/editor_basics/src/org/jetbrains/tutorials/editor/basics/MyTypedHandler.java new file mode 100644 index 000000000..56f8218cf --- /dev/null +++ b/editor_basics/src/org/jetbrains/tutorials/editor/basics/MyTypedHandler.java @@ -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); + } +} diff --git a/facet_basics/resources/META-INF/plugin.xml b/facet_basics/resources/META-INF/plugin.xml new file mode 100644 index 000000000..5b15982c7 --- /dev/null +++ b/facet_basics/resources/META-INF/plugin.xml @@ -0,0 +1,36 @@ + + com.intellij.tutorials.facet + Facet Demo + 1.0 + JetBrains + + Basic example of working with facets + + Initial commit + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/facet_basics/src/com/intellij/tutorials/facet/DemoFacet.java b/facet_basics/src/com/intellij/tutorials/facet/DemoFacet.java new file mode 100644 index 000000000..804f6d1a4 --- /dev/null +++ b/facet_basics/src/com/intellij/tutorials/facet/DemoFacet.java @@ -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 { + 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); + } +} diff --git a/facet_basics/src/com/intellij/tutorials/facet/DemoFacetConfiguration.java b/facet_basics/src/com/intellij/tutorials/facet/DemoFacetConfiguration.java new file mode 100644 index 000000000..8ba2f450b --- /dev/null +++ b/facet_basics/src/com/intellij/tutorials/facet/DemoFacetConfiguration.java @@ -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); + } +} diff --git a/facet_basics/src/com/intellij/tutorials/facet/DemoFacetType.java b/facet_basics/src/com/intellij/tutorials/facet/DemoFacetType.java new file mode 100644 index 000000000..f1664fd45 --- /dev/null +++ b/facet_basics/src/com/intellij/tutorials/facet/DemoFacetType.java @@ -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 { + private static final FacetTypeId TYPE_ID = new FacetTypeId(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; + } +} diff --git a/framework/resources/META-INF/plugin.xml b/framework/resources/META-INF/plugin.xml new file mode 100644 index 000000000..c79474e20 --- /dev/null +++ b/framework/resources/META-INF/plugin.xml @@ -0,0 +1,36 @@ + + com.intellij.demo.framework + Framework example + 1.0 + YourCompany + + Framework support tutorial + + Initial commit + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/framework/src/com/intellij/tutorials/framework/DemoFramework.java b/framework/src/com/intellij/tutorials/framework/DemoFramework.java new file mode 100644 index 000000000..6c4db74e7 --- /dev/null +++ b/framework/src/com/intellij/tutorials/framework/DemoFramework.java @@ -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; + } +} diff --git a/gradle_plugin_demo/build.gradle b/gradle_plugin_demo/build.gradle new file mode 100644 index 000000000..33e6bee8d --- /dev/null +++ b/gradle_plugin_demo/build.gradle @@ -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 () +} \ No newline at end of file diff --git a/gradle_plugin_demo/gradle/wrapper/gradle-wrapper.jar b/gradle_plugin_demo/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..30d399d8d Binary files /dev/null and b/gradle_plugin_demo/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle_plugin_demo/gradle/wrapper/gradle-wrapper.properties b/gradle_plugin_demo/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..39e4717cb --- /dev/null +++ b/gradle_plugin_demo/gradle/wrapper/gradle-wrapper.properties @@ -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 diff --git a/gradle_plugin_demo/gradlew b/gradle_plugin_demo/gradlew new file mode 100644 index 000000000..91a7e269e --- /dev/null +++ b/gradle_plugin_demo/gradlew @@ -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 "$@" diff --git a/gradle_plugin_demo/gradlew.bat b/gradle_plugin_demo/gradlew.bat new file mode 100644 index 000000000..8a0b282aa --- /dev/null +++ b/gradle_plugin_demo/gradlew.bat @@ -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 diff --git a/gradle_plugin_demo/src/main/java/HelloAction.java b/gradle_plugin_demo/src/main/java/HelloAction.java new file mode 100644 index 000000000..b0462638a --- /dev/null +++ b/gradle_plugin_demo/src/main/java/HelloAction.java @@ -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()); + } +} \ No newline at end of file diff --git a/gradle_plugin_demo/src/main/resources/META-INF/plugin.xml b/gradle_plugin_demo/src/main/resources/META-INF/plugin.xml new file mode 100644 index 000000000..6ff607a5a --- /dev/null +++ b/gradle_plugin_demo/src/main/resources/META-INF/plugin.xml @@ -0,0 +1,41 @@ + + org.jetbrains + gradle_plugin_demo + 0.0.1 + dummy + + + ]]> + + + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/inspection/resources/META-INF/plugin.xml b/inspection/resources/META-INF/plugin.xml new file mode 100644 index 000000000..f978c00de --- /dev/null +++ b/inspection/resources/META-INF/plugin.xml @@ -0,0 +1,30 @@ + + com.intellij.tutorials.inspection + Inspection Demo + 1.0 + JetBrains + + Basic example of working with code inspections + + Initial commit + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/inspection/src/com/intellij/tutorials/inspection/DemoCodeInspection.java b/inspection/src/com/intellij/tutorials/inspection/DemoCodeInspection.java new file mode 100644 index 000000000..7b88a1055 --- /dev/null +++ b/inspection/src/com/intellij/tutorials/inspection/DemoCodeInspection.java @@ -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(); + } +} diff --git a/inspection/src/com/intellij/tutorials/inspection/DemoInspectionToolProvider.java b/inspection/src/com/intellij/tutorials/inspection/DemoInspectionToolProvider.java new file mode 100644 index 000000000..aad593a5c --- /dev/null +++ b/inspection/src/com/intellij/tutorials/inspection/DemoInspectionToolProvider.java @@ -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}; + } +} diff --git a/inspection/src/com/intellij/tutorials/inspection/DemoInspectionVisitor.java b/inspection/src/com/intellij/tutorials/inspection/DemoInspectionVisitor.java new file mode 100644 index 000000000..96e73fe5c --- /dev/null +++ b/inspection/src/com/intellij/tutorials/inspection/DemoInspectionVisitor.java @@ -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); + } +} diff --git a/inspection/src/inspectionDescriptions/DemoCode.html b/inspection/src/inspectionDescriptions/DemoCode.html new file mode 100644 index 000000000..942f318aa --- /dev/null +++ b/inspection/src/inspectionDescriptions/DemoCode.html @@ -0,0 +1,7 @@ + + +Write your description here. + +Text after this comment will not be shown in tooltips. + + \ No newline at end of file diff --git a/kotlin_demo/resources/META-INF/plugin.xml b/kotlin_demo/resources/META-INF/plugin.xml new file mode 100644 index 000000000..a61f95cc8 --- /dev/null +++ b/kotlin_demo/resources/META-INF/plugin.xml @@ -0,0 +1,38 @@ + + org.jetbrains + kotlin_demo + 1.0 + YourCompany + + + most HTML tags may be used + ]]> + + + most HTML tags may be used + ]]> + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kotlin_demo/src/HelloAction.kt b/kotlin_demo/src/HelloAction.kt new file mode 100644 index 000000000..7ddc6d7bb --- /dev/null +++ b/kotlin_demo/src/HelloAction.kt @@ -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()) + } +} \ No newline at end of file diff --git a/live_templates/resources/META-INF/plugin.xml b/live_templates/resources/META-INF/plugin.xml new file mode 100644 index 000000000..1e2935c91 --- /dev/null +++ b/live_templates/resources/META-INF/plugin.xml @@ -0,0 +1,37 @@ + + live_templates + live_templates + 1.0 + YourCompany + + + most HTML tags may be used + ]]> + + + most HTML tags may be used + ]]> + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/live_templates/resources/liveTemplates/Markdown.xml b/live_templates/resources/liveTemplates/Markdown.xml new file mode 100644 index 000000000..c7788d82b --- /dev/null +++ b/live_templates/resources/liveTemplates/Markdown.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/live_templates/src/MarkdownContext.java b/live_templates/src/MarkdownContext.java new file mode 100644 index 000000000..1c1c05a6d --- /dev/null +++ b/live_templates/src/MarkdownContext.java @@ -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"); + } +} diff --git a/live_templates/src/MarkdownTemplateProvider.java b/live_templates/src/MarkdownTemplateProvider.java new file mode 100644 index 000000000..c113accb3 --- /dev/null +++ b/live_templates/src/MarkdownTemplateProvider.java @@ -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]; + } +} diff --git a/max_opened_projects/resources/META-INF/plugin.xml b/max_opened_projects/resources/META-INF/plugin.xml new file mode 100644 index 000000000..d844bd01e --- /dev/null +++ b/max_opened_projects/resources/META-INF/plugin.xml @@ -0,0 +1,29 @@ + + max_opened_projects + short description of the plugin + 1.0 + YourCompany + + + + + + + + + + MyPackage.MaxProject + + + + + + + + + + + + + + \ No newline at end of file diff --git a/max_opened_projects/src/MyPackage/MaxProject.java b/max_opened_projects/src/MyPackage/MaxProject.java new file mode 100644 index 000000000..dbf179d55 --- /dev/null +++ b/max_opened_projects/src/MyPackage/MaxProject.java @@ -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(); + } +} diff --git a/max_opened_projects/src/MyPackage/MyCounter.java b/max_opened_projects/src/MyPackage/MyCounter.java new file mode 100644 index 000000000..f2e5417a8 --- /dev/null +++ b/max_opened_projects/src/MyPackage/MyCounter.java @@ -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; + } + +} diff --git a/module/resources/META-INF/plugin.xml b/module/resources/META-INF/plugin.xml new file mode 100644 index 000000000..2b6c1bab7 --- /dev/null +++ b/module/resources/META-INF/plugin.xml @@ -0,0 +1,36 @@ + + com.intellij.tutorials.module + Module Type Demo + 1.0 + JetBrains + + Basic example of working with module types + + Initial commit + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/module/src/com/intellij/tutorials/module/DemoModuleBuilder.java b/module/src/com/intellij/tutorials/module/DemoModuleBuilder.java new file mode 100644 index 000000000..23417dcbc --- /dev/null +++ b/module/src/com/intellij/tutorials/module/DemoModuleBuilder.java @@ -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(); + } +} diff --git a/module/src/com/intellij/tutorials/module/DemoModuleType.java b/module/src/com/intellij/tutorials/module/DemoModuleType.java new file mode 100644 index 000000000..e43e92f80 --- /dev/null +++ b/module/src/com/intellij/tutorials/module/DemoModuleType.java @@ -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 { + 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); + } +} diff --git a/module/src/com/intellij/tutorials/module/DemoModuleWizardStep.java b/module/src/com/intellij/tutorials/module/DemoModuleWizardStep.java new file mode 100644 index 000000000..4227d9e4d --- /dev/null +++ b/module/src/com/intellij/tutorials/module/DemoModuleWizardStep.java @@ -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 + } +} diff --git a/plugin_sample/resources/META-INF/plugin.xml b/plugin_sample/resources/META-INF/plugin.xml new file mode 100644 index 000000000..96ef64d6c --- /dev/null +++ b/plugin_sample/resources/META-INF/plugin.xml @@ -0,0 +1,140 @@ + + org.jetbrains.plugins.sample.PluginSample + Basic plugin example + 1.0 + JetBrains + Samples + + most HTML tags may be used + ]]> + + most HTML tags may be used + ]]> + + + + + + com.intellij.modules.lang + + + + + + + + + + + org.jetbrains.tutorials.sample.PluginSampleBundle + + + + + + org.jetbrains.tutorials.sample.DummyApplicationComponent + + org.jetbrains.tutorials.sample.DummyApplicationComponentImpl + + + + + + + + org.jetbrains.tutorials.sample.DummyProjectComponent + org.jetbrains.tutorials.sample.DummyProjectComponentImpl + + + + + + + + + org.jetbrains.tutorials.sample.DummyModuleComponent + org.jetbrains.tutorials.sample.DummyModuleComponentImpl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugin_sample/resources/org/jetbrains/tutorials/sample/PluginSampleBundle.properties b/plugin_sample/resources/org/jetbrains/tutorials/sample/PluginSampleBundle.properties new file mode 100644 index 000000000..4b1033298 --- /dev/null +++ b/plugin_sample/resources/org/jetbrains/tutorials/sample/PluginSampleBundle.properties @@ -0,0 +1 @@ +key=value \ No newline at end of file diff --git a/plugin_sample/src/org/jetbrains/tutorials/sample/DummyApplicationComponent.java b/plugin_sample/src/org/jetbrains/tutorials/sample/DummyApplicationComponent.java new file mode 100644 index 000000000..9dc24acde --- /dev/null +++ b/plugin_sample/src/org/jetbrains/tutorials/sample/DummyApplicationComponent.java @@ -0,0 +1,9 @@ +package org.jetbrains.tutorials.sample; + +import com.intellij.openapi.components.ApplicationComponent; + +/** + * @author Anna Bulenkova + */ +interface DummyApplicationComponent extends ApplicationComponent{ +} diff --git a/plugin_sample/src/org/jetbrains/tutorials/sample/DummyApplicationComponentImpl.java b/plugin_sample/src/org/jetbrains/tutorials/sample/DummyApplicationComponentImpl.java new file mode 100644 index 000000000..2f4f7330b --- /dev/null +++ b/plugin_sample/src/org/jetbrains/tutorials/sample/DummyApplicationComponentImpl.java @@ -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"; + } +} diff --git a/plugin_sample/src/org/jetbrains/tutorials/sample/DummyModuleComponent.java b/plugin_sample/src/org/jetbrains/tutorials/sample/DummyModuleComponent.java new file mode 100644 index 000000000..ae065c9c4 --- /dev/null +++ b/plugin_sample/src/org/jetbrains/tutorials/sample/DummyModuleComponent.java @@ -0,0 +1,9 @@ +package org.jetbrains.tutorials.sample; + +import com.intellij.openapi.module.ModuleComponent; + +/** + * @author Anna Bulenkova + */ +public interface DummyModuleComponent extends ModuleComponent{ +} diff --git a/plugin_sample/src/org/jetbrains/tutorials/sample/DummyModuleComponentImpl.java b/plugin_sample/src/org/jetbrains/tutorials/sample/DummyModuleComponentImpl.java new file mode 100644 index 000000000..22231fd71 --- /dev/null +++ b/plugin_sample/src/org/jetbrains/tutorials/sample/DummyModuleComponentImpl.java @@ -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"; + } +} diff --git a/plugin_sample/src/org/jetbrains/tutorials/sample/DummyProjectComponent.java b/plugin_sample/src/org/jetbrains/tutorials/sample/DummyProjectComponent.java new file mode 100644 index 000000000..b49347acd --- /dev/null +++ b/plugin_sample/src/org/jetbrains/tutorials/sample/DummyProjectComponent.java @@ -0,0 +1,9 @@ +package org.jetbrains.tutorials.sample; + +import com.intellij.openapi.components.ProjectComponent; + +/** + * @author Anna Bulenkova + */ +public interface DummyProjectComponent extends ProjectComponent{ +} diff --git a/plugin_sample/src/org/jetbrains/tutorials/sample/DummyProjectComponentImpl.java b/plugin_sample/src/org/jetbrains/tutorials/sample/DummyProjectComponentImpl.java new file mode 100644 index 000000000..fac9b6bd0 --- /dev/null +++ b/plugin_sample/src/org/jetbrains/tutorials/sample/DummyProjectComponentImpl.java @@ -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"; + } +} diff --git a/plugin_sample/src/org/jetbrains/tutorials/sample/actions/DummyActionGroup.java b/plugin_sample/src/org/jetbrains/tutorials/sample/actions/DummyActionGroup.java new file mode 100644 index 000000000..f55cfa613 --- /dev/null +++ b/plugin_sample/src/org/jetbrains/tutorials/sample/actions/DummyActionGroup.java @@ -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]; + } +} diff --git a/plugin_sample/src/org/jetbrains/tutorials/sample/actions/GroupedAction.java b/plugin_sample/src/org/jetbrains/tutorials/sample/actions/GroupedAction.java new file mode 100644 index 000000000..7e665e74d --- /dev/null +++ b/plugin_sample/src/org/jetbrains/tutorials/sample/actions/GroupedAction.java @@ -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) { + + } +} diff --git a/plugin_sample/src/org/jetbrains/tutorials/sample/actions/GroupedToDefaultAction.java b/plugin_sample/src/org/jetbrains/tutorials/sample/actions/GroupedToDefaultAction.java new file mode 100644 index 000000000..7f99e2f10 --- /dev/null +++ b/plugin_sample/src/org/jetbrains/tutorials/sample/actions/GroupedToDefaultAction.java @@ -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) { + + } +} diff --git a/plugin_sample/src/org/jetbrains/tutorials/sample/actions/SimpleAction.java b/plugin_sample/src/org/jetbrains/tutorials/sample/actions/SimpleAction.java new file mode 100644 index 000000000..6484c780c --- /dev/null +++ b/plugin_sample/src/org/jetbrains/tutorials/sample/actions/SimpleAction.java @@ -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); + } +} diff --git a/project_model/resources/META-INF/plugin.xml b/project_model/resources/META-INF/plugin.xml new file mode 100644 index 000000000..0de45090a --- /dev/null +++ b/project_model/resources/META-INF/plugin.xml @@ -0,0 +1,55 @@ + + org.jetbrains.plugins.sample.ProjectModel + Editor basics + 1.0 + JetBrains + + Project model illustration + + Initial commit + + + + com.intellij.modules.lang + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/project_model/src/com/intellij/tutorials/project/model/LibrariesAction.java b/project_model/src/com/intellij/tutorials/project/model/LibrariesAction.java new file mode 100644 index 000000000..dd53d59dd --- /dev/null +++ b/project_model/src/com/intellij/tutorials/project/model/LibrariesAction.java @@ -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"); + } + } + } +} diff --git a/project_model/src/com/intellij/tutorials/project/model/ModificationAction.java b/project_model/src/com/intellij/tutorials/project/model/ModificationAction.java new file mode 100644 index 000000000..f3919faa6 --- /dev/null +++ b/project_model/src/com/intellij/tutorials/project/model/ModificationAction.java @@ -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); + } +} diff --git a/project_model/src/com/intellij/tutorials/project/model/ProjectFileIndexSampleAction.java b/project_model/src/com/intellij/tutorials/project/model/ProjectFileIndexSampleAction.java new file mode 100644 index 000000000..efe8c1da3 --- /dev/null +++ b/project_model/src/com/intellij/tutorials/project/model/ProjectFileIndexSampleAction.java @@ -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()); + } + } +} diff --git a/project_model/src/com/intellij/tutorials/project/model/ProjectSdkAction.java b/project_model/src/com/intellij/tutorials/project/model/ProjectSdkAction.java new file mode 100644 index 000000000..b030992f2 --- /dev/null +++ b/project_model/src/com/intellij/tutorials/project/model/ProjectSdkAction.java @@ -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); + } + } +} diff --git a/project_model/src/com/intellij/tutorials/project/model/ShowSourceRootsActions.java b/project_model/src/com/intellij/tutorials/project/model/ShowSourceRootsActions.java new file mode 100644 index 000000000..2a7d5e527 --- /dev/null +++ b/project_model/src/com/intellij/tutorials/project/model/ShowSourceRootsActions.java @@ -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); + } +} diff --git a/project_view_pane/resources/META-INF/plugin.xml b/project_view_pane/resources/META-INF/plugin.xml new file mode 100644 index 000000000..1a6ab3cd2 --- /dev/null +++ b/project_view_pane/resources/META-INF/plugin.xml @@ -0,0 +1,30 @@ + + org.jetbrains.plugins.sample.ProjectViewPane + Project View Pain Demo + 1.0 + JetBrains + + Project View Pain Demo + + Initial commit + + + + com.intellij.modules.lang + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/project_view_pane/src/org/jetbrains/tutorials/view/pane/ImagesProjectNode.java b/project_view_pane/src/org/jetbrains/tutorials/view/pane/ImagesProjectNode.java new file mode 100644 index 000000000..6c44feb53 --- /dev/null +++ b/project_view_pane/src/org/jetbrains/tutorials/view/pane/ImagesProjectNode.java @@ -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 { + private static final Key> 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 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 getImagesFiles(Project project) { + Set files = project.getUserData(IMAGES_PROJECT_DIRS); + if (files == null) { + files = new HashSet(); + project.putUserData(IMAGES_PROJECT_DIRS, files); + } + return files; + } + + @Override + protected VirtualFile getVirtualFile() { + return getValue(); + } + + @NotNull + @Override + public Collection getChildren() { + final List files = new ArrayList(0); + for (VirtualFile file : getValue().getChildren()) { + if (getImagesFiles(myProject).contains(file)) { + files.add(file); + } + } + if (files.isEmpty()) return Collections.emptyList(); + final List nodes = new ArrayList(files.size()); + final boolean alwaysOnTop = ((ProjectViewImpl) ProjectView.getInstance(myProject)).isFoldersAlwaysOnTop(); + Collections.sort(files, new Comparator() { + @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); + } + } + }); + } +} + diff --git a/project_view_pane/src/org/jetbrains/tutorials/view/pane/ImagesProjectViewPane.java b/project_view_pane/src/org/jetbrains/tutorials/view/pane/ImagesProjectViewPane.java new file mode 100644 index 000000000..b95985af1 --- /dev/null +++ b/project_view_pane/src/org/jetbrains/tutorials/view/pane/ImagesProjectViewPane.java @@ -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); + } +} + diff --git a/project_wizard/resources/META-INF/plugin.xml b/project_wizard/resources/META-INF/plugin.xml new file mode 100644 index 000000000..63ac241ac --- /dev/null +++ b/project_wizard/resources/META-INF/plugin.xml @@ -0,0 +1,31 @@ + + org.jetbrains.tutorials.ProjectWizard + Project Wizard Demo + 1.0 + JetBrains + + Illustration of working with Project Wizard + + Initial commit + + + + com.intellij.modules.lang + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/project_wizard/src/org/jetbrains/tutorials/project/wizard/DemoModuleWizardStep.java b/project_wizard/src/org/jetbrains/tutorials/project/wizard/DemoModuleWizardStep.java new file mode 100644 index 000000000..6fb234c78 --- /dev/null +++ b/project_wizard/src/org/jetbrains/tutorials/project/wizard/DemoModuleWizardStep.java @@ -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() { + + } + }}; + } +} diff --git a/register_actions/resources/META-INF/plugin.xml b/register_actions/resources/META-INF/plugin.xml new file mode 100644 index 000000000..23142be67 --- /dev/null +++ b/register_actions/resources/META-INF/plugin.xml @@ -0,0 +1,83 @@ + + org.jetbrains.plugins.sample.RegisterActions + Sample plugin for working with IntelliJ Action System + 1.0 + JetBrains + + Illustration of Action System + + Initial commit + + + + com.intellij.modules.lang + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/register_actions/src/org/jetbrains/tutorials/actions/BaseActionGroup.java b/register_actions/src/org/jetbrains/tutorials/actions/BaseActionGroup.java new file mode 100644 index 000000000..499e5bf72 --- /dev/null +++ b/register_actions/src/org/jetbrains/tutorials/actions/BaseActionGroup.java @@ -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 + } + } +} diff --git a/register_actions/src/org/jetbrains/tutorials/actions/CustomDefaultActionGroup.java b/register_actions/src/org/jetbrains/tutorials/actions/CustomDefaultActionGroup.java new file mode 100644 index 000000000..cb24193af --- /dev/null +++ b/register_actions/src/org/jetbrains/tutorials/actions/CustomDefaultActionGroup.java @@ -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); + } +} diff --git a/register_actions/src/org/jetbrains/tutorials/actions/CustomGroupedAction.java b/register_actions/src/org/jetbrains/tutorials/actions/CustomGroupedAction.java new file mode 100644 index 000000000..77444a508 --- /dev/null +++ b/register_actions/src/org/jetbrains/tutorials/actions/CustomGroupedAction.java @@ -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 + } +} diff --git a/register_actions/src/org/jetbrains/tutorials/actions/GroupedAction.java b/register_actions/src/org/jetbrains/tutorials/actions/GroupedAction.java new file mode 100644 index 000000000..abdb9e824 --- /dev/null +++ b/register_actions/src/org/jetbrains/tutorials/actions/GroupedAction.java @@ -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 + } +} diff --git a/register_actions/src/org/jetbrains/tutorials/actions/SimpleAction.java b/register_actions/src/org/jetbrains/tutorials/actions/SimpleAction.java new file mode 100644 index 000000000..48ba91cd8 --- /dev/null +++ b/register_actions/src/org/jetbrains/tutorials/actions/SimpleAction.java @@ -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); + } +} diff --git a/run_configuration/resources/META-INF/plugin.xml b/run_configuration/resources/META-INF/plugin.xml new file mode 100644 index 000000000..e29508754 --- /dev/null +++ b/run_configuration/resources/META-INF/plugin.xml @@ -0,0 +1,30 @@ + + org.jetbrains.tutorials.run.configuration + Run Configuration + 1.0 + JetBrains + + Illustration of working with run configurations + + Initial commit + + + + com.intellij.modules.lang + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoConfigurationFactory.java b/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoConfigurationFactory.java new file mode 100644 index 000000000..a475e8373 --- /dev/null +++ b/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoConfigurationFactory.java @@ -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; + } +} diff --git a/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoRunConfiguration.java b/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoRunConfiguration.java new file mode 100644 index 000000000..1ab7c7de3 --- /dev/null +++ b/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoRunConfiguration.java @@ -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 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; + } +} diff --git a/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoRunConfigurationType.java b/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoRunConfigurationType.java new file mode 100644 index 000000000..bac651411 --- /dev/null +++ b/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoRunConfigurationType.java @@ -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)}; + } +} diff --git a/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoSettingsEditor.form b/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoSettingsEditor.form new file mode 100644 index 000000000..d9dd1f253 --- /dev/null +++ b/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoSettingsEditor.form @@ -0,0 +1,29 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoSettingsEditor.java b/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoSettingsEditor.java new file mode 100644 index 000000000..db66fec90 --- /dev/null +++ b/run_configuration/src/org/jetbrains/tutorials/run/configuration/DemoSettingsEditor.java @@ -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 { + private JPanel myPanel; + private LabeledComponent 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(); + myMainClass.setComponent(new TextFieldWithBrowseButton()); + } +} + diff --git a/simple_language_plugin/JFlex.jar b/simple_language_plugin/JFlex.jar new file mode 100644 index 000000000..8bef2fdba Binary files /dev/null and b/simple_language_plugin/JFlex.jar differ diff --git a/simple_language_plugin/gen/com/simpleplugin/parser/SimpleParser.java b/simple_language_plugin/gen/com/simpleplugin/parser/SimpleParser.java new file mode 100644 index 000000000..3e28b7da7 --- /dev/null +++ b/simple_language_plugin/gen/com/simpleplugin/parser/SimpleParser.java @@ -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, "", KEY, SEPARATOR)) return false; + boolean r; + Marker m = enter_section_(b, l, _NONE_, ""); + 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; + } + +} diff --git a/simple_language_plugin/gen/com/simpleplugin/psi/SimpleProperty.java b/simple_language_plugin/gen/com/simpleplugin/psi/SimpleProperty.java new file mode 100644 index 000000000..2ff5df042 --- /dev/null +++ b/simple_language_plugin/gen/com/simpleplugin/psi/SimpleProperty.java @@ -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(); + +} diff --git a/simple_language_plugin/gen/com/simpleplugin/psi/SimpleTypes.java b/simple_language_plugin/gen/com/simpleplugin/psi/SimpleTypes.java new file mode 100644 index 000000000..36792334c --- /dev/null +++ b/simple_language_plugin/gen/com/simpleplugin/psi/SimpleTypes.java @@ -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); + } + } +} diff --git a/simple_language_plugin/gen/com/simpleplugin/psi/SimpleVisitor.java b/simple_language_plugin/gen/com/simpleplugin/psi/SimpleVisitor.java new file mode 100644 index 000000000..504829968 --- /dev/null +++ b/simple_language_plugin/gen/com/simpleplugin/psi/SimpleVisitor.java @@ -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); + } + +} diff --git a/simple_language_plugin/gen/com/simpleplugin/psi/impl/SimplePropertyImpl.java b/simple_language_plugin/gen/com/simpleplugin/psi/impl/SimplePropertyImpl.java new file mode 100644 index 000000000..7c0abca71 --- /dev/null +++ b/simple_language_plugin/gen/com/simpleplugin/psi/impl/SimplePropertyImpl.java @@ -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); + } + +} diff --git a/simple_language_plugin/idea-flex.skeleton b/simple_language_plugin/idea-flex.skeleton new file mode 100644 index 000000000..234a62c41 --- /dev/null +++ b/simple_language_plugin/idea-flex.skeleton @@ -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 false, 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 pos 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 + +} diff --git a/simple_language_plugin/resources/META-INF/plugin.xml b/simple_language_plugin/resources/META-INF/plugin.xml new file mode 100644 index 000000000..601bc4d54 --- /dev/null +++ b/simple_language_plugin/resources/META-INF/plugin.xml @@ -0,0 +1,60 @@ + + com.simpleplugin.unique.plugin.id + Simple + 1.0 + YourCompany + + + most HTML tags may be used + ]]> + + + most HTML tags may be used + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/simple_language_plugin/src/com/simpleplugin/CreatePropertyQuickFix.java b/simple_language_plugin/src/com/simpleplugin/CreatePropertyQuickFix.java new file mode 100644 index 000000000..add125e7d --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/CreatePropertyQuickFix.java @@ -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 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(); + } +} diff --git a/simple_language_plugin/src/com/simpleplugin/Simple.bnf b/simple_language_plugin/src/com/simpleplugin/Simple.bnf new file mode 100644 index 000000000..d5ca3cef2 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/Simple.bnf @@ -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]} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/Simple.flex b/simple_language_plugin/src/com/simpleplugin/Simple.flex new file mode 100644 index 000000000..89dabf207 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/Simple.flex @@ -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 + +%% + + {END_OF_LINE_COMMENT} { yybegin(YYINITIAL); return SimpleTypes.COMMENT; } + + {KEY_CHARACTER}+ { yybegin(YYINITIAL); return SimpleTypes.KEY; } + + {SEPARATOR} { yybegin(WAITING_VALUE); return SimpleTypes.SEPARATOR; } + + {CRLF}({CRLF}|{WHITE_SPACE})+ { yybegin(YYINITIAL); return TokenType.WHITE_SPACE; } + + {WHITE_SPACE}+ { yybegin(WAITING_VALUE); return TokenType.WHITE_SPACE; } + + {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; } diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleAnnotator.java b/simple_language_plugin/src/com/simpleplugin/SimpleAnnotator.java new file mode 100644 index 000000000..e0425c5cc --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleAnnotator.java @@ -0,0 +1,41 @@ +package com.simpleplugin; + +import com.intellij.lang.annotation.Annotation; +import com.intellij.lang.annotation.AnnotationHolder; +import com.intellij.lang.annotation.Annotator; +import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiLiteralExpression; +import com.simpleplugin.psi.SimpleProperty; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class SimpleAnnotator implements Annotator { + @Override + public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) { + if (element instanceof PsiLiteralExpression) { + PsiLiteralExpression literalExpression = (PsiLiteralExpression) element; + String value = literalExpression.getValue() instanceof String ? (String)literalExpression.getValue() : null; + + if (value != null && value.startsWith("simple"+":")) { + Project project = element.getProject(); + String key = value.substring(7); + List properties = SimpleUtil.findProperties(project, key); + if (properties.size() == 1) { + TextRange range = new TextRange(element.getTextRange().getStartOffset() + 7, + element.getTextRange().getStartOffset() + 7); + Annotation annotation = holder.createInfoAnnotation(range, null); + annotation.setTextAttributes(DefaultLanguageHighlighterColors.LINE_COMMENT); + } else if (properties.size() == 0) { + TextRange range = new TextRange(element.getTextRange().getStartOffset() + 8, + element.getTextRange().getEndOffset()); + holder.createErrorAnnotation(range, "Unresolved property"). + registerFix(new CreatePropertyQuickFix(key)); + } + } + } + } +} diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleBlock.java b/simple_language_plugin/src/com/simpleplugin/SimpleBlock.java new file mode 100644 index 000000000..9c1b723a0 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleBlock.java @@ -0,0 +1,57 @@ +package com.simpleplugin; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.TokenType; +import com.intellij.psi.formatter.common.AbstractBlock; +import com.simpleplugin.psi.SimpleTypes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class SimpleBlock extends AbstractBlock { + private SpacingBuilder spacingBuilder; + + protected SimpleBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment, + SpacingBuilder spacingBuilder) { + super(node, wrap, alignment); + this.spacingBuilder = spacingBuilder; + } + + @Override + protected List buildChildren() { + List blocks = new ArrayList(); + ASTNode child = myNode.getFirstChildNode(); + ASTNode previousChild = null; + while (child != null) { + if (child.getElementType() != TokenType.WHITE_SPACE && + (previousChild == null || previousChild.getElementType() != SimpleTypes.CRLF || + child.getElementType() != SimpleTypes.CRLF)) { + Block block = new SimpleBlock(child, Wrap.createWrap(WrapType.NONE, false), Alignment.createAlignment(), + spacingBuilder); + blocks.add(block); + } + previousChild = child; + child = child.getTreeNext(); + } + return blocks; + } + + @Override + public Indent getIndent() { + return Indent.getNoneIndent(); + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return spacingBuilder.getSpacing(this, child1, child2); + } + + @Override + public boolean isLeaf() { + return myNode.getFirstChildNode() == null; + } +} diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleChooseByNameContributor.java b/simple_language_plugin/src/com/simpleplugin/SimpleChooseByNameContributor.java new file mode 100644 index 000000000..1ec9f06ed --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleChooseByNameContributor.java @@ -0,0 +1,33 @@ +package com.simpleplugin; + +import com.intellij.navigation.ChooseByNameContributor; +import com.intellij.navigation.NavigationItem; +import com.intellij.openapi.project.Project; +import com.simpleplugin.psi.SimpleProperty; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class SimpleChooseByNameContributor implements ChooseByNameContributor { + @NotNull + @Override + public String[] getNames(Project project, boolean includeNonProjectItems) { + List properties = SimpleUtil.findProperties(project); + List names = new ArrayList(properties.size()); + for (SimpleProperty property : properties) { + if (property.getKey() != null && property.getKey().length() > 0) { + names.add(property.getKey()); + } + } + return names.toArray(new String[names.size()]); + } + + @NotNull + @Override + public NavigationItem[] getItemsByName(String name, String pattern, Project project, boolean includeNonProjectItems) { + // todo include non project items + List properties = SimpleUtil.findProperties(project, name); + return properties.toArray(new NavigationItem[properties.size()]); + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleCodeStyleSettings.java b/simple_language_plugin/src/com/simpleplugin/SimpleCodeStyleSettings.java new file mode 100644 index 000000000..bb62cdb4c --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleCodeStyleSettings.java @@ -0,0 +1,10 @@ +package com.simpleplugin; + +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CustomCodeStyleSettings; + +public class SimpleCodeStyleSettings extends CustomCodeStyleSettings { + public SimpleCodeStyleSettings(CodeStyleSettings settings) { + super("SimpleCodeStyleSettings", settings); + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleCodeStyleSettingsProvider.java b/simple_language_plugin/src/com/simpleplugin/SimpleCodeStyleSettingsProvider.java new file mode 100644 index 000000000..f19dc35b8 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleCodeStyleSettingsProvider.java @@ -0,0 +1,47 @@ +package com.simpleplugin; + +import com.intellij.application.options.CodeStyleAbstractConfigurable; +import com.intellij.application.options.CodeStyleAbstractPanel; +import com.intellij.application.options.TabbedLanguageCodeStylePanel; +import com.intellij.openapi.options.Configurable; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsProvider; +import com.intellij.psi.codeStyle.CustomCodeStyleSettings; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class SimpleCodeStyleSettingsProvider extends CodeStyleSettingsProvider { + @Override + public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings) { + return new SimpleCodeStyleSettings(settings); + } + + @Nullable + @Override + public String getConfigurableDisplayName() { + return "Simple"; + } + + @NotNull + @Override + public Configurable createSettingsPage(CodeStyleSettings settings, CodeStyleSettings originalSettings) { + return new CodeStyleAbstractConfigurable(settings, originalSettings, "Simple") { + @Override + protected CodeStyleAbstractPanel createPanel(CodeStyleSettings settings) { + return new SimpleCodeStyleMainPanel(getCurrentSettings(), settings); + } + + @Nullable + @Override + public String getHelpTopic() { + return null; + } + }; + } + + private static class SimpleCodeStyleMainPanel extends TabbedLanguageCodeStylePanel { + public SimpleCodeStyleMainPanel(CodeStyleSettings currentSettings, CodeStyleSettings settings) { + super(SimpleLanguage.INSTANCE, currentSettings, settings); + } + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleColorSettingsPage.java b/simple_language_plugin/src/com/simpleplugin/SimpleColorSettingsPage.java new file mode 100644 index 000000000..489aede15 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleColorSettingsPage.java @@ -0,0 +1,73 @@ +package com.simpleplugin; + +import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.fileTypes.SyntaxHighlighter; +import com.intellij.openapi.options.colors.AttributesDescriptor; +import com.intellij.openapi.options.colors.ColorDescriptor; +import com.intellij.openapi.options.colors.ColorSettingsPage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.Map; + +public class SimpleColorSettingsPage implements ColorSettingsPage { + private static final AttributesDescriptor[] DESCRIPTORS = new AttributesDescriptor[]{ + new AttributesDescriptor("Key", SimpleSyntaxHighlighter.KEY), + new AttributesDescriptor("Separator", SimpleSyntaxHighlighter.SEPARATOR), + new AttributesDescriptor("Value", SimpleSyntaxHighlighter.VALUE), + }; + + @Nullable + @Override + public Icon getIcon() { + return SimpleIcons.FILE; + } + + @NotNull + @Override + public SyntaxHighlighter getHighlighter() { + return new SimpleSyntaxHighlighter(); + } + + @NotNull + @Override + public String getDemoText() { + return "# You are reading the \".properties\" entry.\n" + + "! The exclamation mark can also mark text as comments.\n" + + "website = http://en.wikipedia.org/\n" + + "language = English\n" + + "# The backslash below tells the application to continue reading\n" + + "# the value onto the next line.\n" + + "message = Welcome to \\\n" + + " Wikipedia!\n" + + "# Add spaces to the key\n" + + "key\\ with\\ spaces = This is the value that could be looked up with the key \"key with spaces\".\n" + + "# Unicode\n" + + "tab : \\u0009"; + } + + @Nullable + @Override + public Map getAdditionalHighlightingTagToDescriptorMap() { + return null; + } + + @NotNull + @Override + public AttributesDescriptor[] getAttributeDescriptors() { + return DESCRIPTORS; + } + + @NotNull + @Override + public ColorDescriptor[] getColorDescriptors() { + return ColorDescriptor.EMPTY_ARRAY; + } + + @NotNull + @Override + public String getDisplayName() { + return "Simple"; + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleCommenter.java b/simple_language_plugin/src/com/simpleplugin/SimpleCommenter.java new file mode 100644 index 000000000..f9f0e24a1 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleCommenter.java @@ -0,0 +1,36 @@ +package com.simpleplugin; + +import com.intellij.lang.Commenter; +import org.jetbrains.annotations.Nullable; + +public class SimpleCommenter implements Commenter { + @Nullable + @Override + public String getLineCommentPrefix() { + return "#"; + } + + @Nullable + @Override + public String getBlockCommentPrefix() { + return ""; + } + + @Nullable + @Override + public String getBlockCommentSuffix() { + return null; + } + + @Nullable + @Override + public String getCommentedBlockCommentPrefix() { + return null; + } + + @Nullable + @Override + public String getCommentedBlockCommentSuffix() { + return null; + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleCompletionContributor.java b/simple_language_plugin/src/com/simpleplugin/SimpleCompletionContributor.java new file mode 100644 index 000000000..1ca45e01e --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleCompletionContributor.java @@ -0,0 +1,23 @@ +package com.simpleplugin; + +import com.intellij.codeInsight.completion.*; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.patterns.PlatformPatterns; +import com.intellij.util.ProcessingContext; +import com.simpleplugin.psi.SimpleTypes; +import org.jetbrains.annotations.NotNull; + +public class SimpleCompletionContributor extends CompletionContributor { + public SimpleCompletionContributor() { + extend(CompletionType.BASIC, + PlatformPatterns.psiElement(SimpleTypes.VALUE).withLanguage(SimpleLanguage.INSTANCE), + new CompletionProvider() { + public void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull CompletionResultSet resultSet) { + resultSet.addElement(LookupElementBuilder.create("Hello")); + } + } + ); + } +} diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleFileType.java b/simple_language_plugin/src/com/simpleplugin/SimpleFileType.java new file mode 100644 index 000000000..3d3714b4d --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleFileType.java @@ -0,0 +1,39 @@ +package com.simpleplugin; + +import com.intellij.openapi.fileTypes.LanguageFileType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +public class SimpleFileType extends LanguageFileType { + public static final SimpleFileType INSTANCE = new SimpleFileType(); + + private SimpleFileType() { + super(SimpleLanguage.INSTANCE); + } + + @NotNull + @Override + public String getName() { + return "Simple file"; + } + + @NotNull + @Override + public String getDescription() { + return "Simple language file"; + } + + @NotNull + @Override + public String getDefaultExtension() { + return "simple"; + } + + @Nullable + @Override + public Icon getIcon() { + return SimpleIcons.FILE; + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleFileTypeFactory.java b/simple_language_plugin/src/com/simpleplugin/SimpleFileTypeFactory.java new file mode 100644 index 000000000..2a09d45be --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleFileTypeFactory.java @@ -0,0 +1,12 @@ +package com.simpleplugin; + +import com.intellij.openapi.fileTypes.FileTypeConsumer; +import com.intellij.openapi.fileTypes.FileTypeFactory; +import org.jetbrains.annotations.NotNull; + +public class SimpleFileTypeFactory extends FileTypeFactory{ + @Override + public void createFileTypes(@NotNull FileTypeConsumer fileTypeConsumer) { + fileTypeConsumer.consume(SimpleFileType.INSTANCE, "simple"); + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleFilterLexer.java b/simple_language_plugin/src/com/simpleplugin/SimpleFilterLexer.java new file mode 100644 index 000000000..78de00162 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleFilterLexer.java @@ -0,0 +1,19 @@ +package com.simpleplugin; + +import com.intellij.lexer.Lexer; +import com.intellij.psi.impl.cache.impl.BaseFilterLexer; +import com.intellij.psi.impl.cache.impl.OccurrenceConsumer; +import com.intellij.psi.search.UsageSearchContext; + +public class SimpleFilterLexer extends BaseFilterLexer { + public SimpleFilterLexer(final Lexer originalLexer, final OccurrenceConsumer table) { + super(originalLexer, table); + } + + @Override + public void advance() { + scanWordsInToken(UsageSearchContext.IN_COMMENTS, false, false); + advanceTodoItemCountsInToken(); + myDelegate.advance(); + } +} diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleFindUsagesProvider.java b/simple_language_plugin/src/com/simpleplugin/SimpleFindUsagesProvider.java new file mode 100644 index 000000000..0d8160cab --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleFindUsagesProvider.java @@ -0,0 +1,62 @@ +package com.simpleplugin; + +import com.intellij.lang.cacheBuilder.DefaultWordsScanner; +import com.intellij.lang.cacheBuilder.WordsScanner; +import com.intellij.lang.findUsages.FindUsagesProvider; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiNamedElement; +import com.intellij.psi.tree.TokenSet; +import com.simpleplugin.psi.SimpleProperty; +import com.simpleplugin.psi.SimpleTypes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class SimpleFindUsagesProvider implements FindUsagesProvider { + @Nullable + @Override + public WordsScanner getWordsScanner() { + return new DefaultWordsScanner(new SimpleLexerAdapter(), + TokenSet.create(SimpleTypes.KEY), TokenSet.create(SimpleTypes.COMMENT), TokenSet.EMPTY); + } + + @Override + public boolean canFindUsagesFor(@NotNull PsiElement psiElement) { + return psiElement instanceof PsiNamedElement; + } + + @Nullable + @Override + public String getHelpId(@NotNull PsiElement psiElement) { + return null; + } + + @NotNull + @Override + public String getType(@NotNull PsiElement element) { + if (element instanceof SimpleProperty) { + return "simple property"; + } else { + return ""; + } + } + + @NotNull + @Override + public String getDescriptiveName(@NotNull PsiElement element) { + if (element instanceof SimpleProperty) { + return ((SimpleProperty) element).getKey(); + } else { + return ""; + } + } + + @NotNull + @Override + public String getNodeText(@NotNull PsiElement element, boolean useFullName) { + if (element instanceof SimpleProperty) { + return ((SimpleProperty) element).getKey() + ":" + ((SimpleProperty) element).getValue(); + } else { + return ""; + } + } +} diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleFoldingBuilder.java b/simple_language_plugin/src/com/simpleplugin/SimpleFoldingBuilder.java new file mode 100644 index 000000000..745726933 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleFoldingBuilder.java @@ -0,0 +1,65 @@ +package com.simpleplugin; + +import com.intellij.lang.ASTNode; +import com.intellij.lang.folding.FoldingBuilderEx; +import com.intellij.lang.folding.FoldingDescriptor; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.FoldingGroup; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiLiteralExpression; +import com.intellij.psi.util.PsiTreeUtil; +import com.simpleplugin.psi.SimpleProperty; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class SimpleFoldingBuilder extends FoldingBuilderEx { + @NotNull + @Override + public FoldingDescriptor[] buildFoldRegions(@NotNull PsiElement root, @NotNull Document document, boolean quick) { + FoldingGroup group = FoldingGroup.newGroup("simple"); + + List descriptors = new ArrayList(); + Collection literalExpressions = PsiTreeUtil.findChildrenOfType(root, PsiLiteralExpression.class); + for (final PsiLiteralExpression literalExpression : literalExpressions) { + String value = literalExpression.getValue() instanceof String ? (String)literalExpression.getValue() : null; + + if (value != null && value.startsWith("simple:")) { + Project project = literalExpression.getProject(); + String key = value.substring(7); + final List properties = SimpleUtil.findProperties(project, key); + if (properties.size() == 1) { + descriptors.add(new FoldingDescriptor(literalExpression.getNode(), + new TextRange(literalExpression.getTextRange().getStartOffset() + 1, + literalExpression.getTextRange().getEndOffset() - 1), group) { + @Nullable + @Override + public String getPlaceholderText() { + // IMPORTANT: keys can come with no values, so a test for null is needed + // IMPORTANT: Convert embedded \n to backslash n, so that the string will look like it has LF embedded in it and embedded " to escaped " + String valueOf = properties.get(0).getValue(); + return valueOf == null ? "" : valueOf.replaceAll("\n","\\n").replaceAll("\"","\\\\\""); + } + }); + } + } + } + return descriptors.toArray(new FoldingDescriptor[descriptors.size()]); + } + + @Nullable + @Override + public String getPlaceholderText(@NotNull ASTNode node) { + return "..."; + } + + @Override + public boolean isCollapsedByDefault(@NotNull ASTNode node) { + return true; + } +} diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleFormattingModelBuilder.java b/simple_language_plugin/src/com/simpleplugin/SimpleFormattingModelBuilder.java new file mode 100644 index 000000000..b20468c77 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleFormattingModelBuilder.java @@ -0,0 +1,33 @@ +package com.simpleplugin; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.simpleplugin.psi.SimpleTypes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class SimpleFormattingModelBuilder implements FormattingModelBuilder { + @NotNull + @Override + public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) { + return FormattingModelProvider.createFormattingModelForPsiFile(element.getContainingFile(), + new SimpleBlock(element.getNode(), Wrap.createWrap(WrapType.NONE, false), + Alignment.createAlignment(), createSpaceBuilder(settings)), settings); + } + + private static SpacingBuilder createSpaceBuilder(CodeStyleSettings settings) { + return new SpacingBuilder(settings, SimpleLanguage.INSTANCE). + around(SimpleTypes.SEPARATOR).spaceIf(settings.SPACE_AROUND_ASSIGNMENT_OPERATORS). + before(SimpleTypes.PROPERTY).none(); + } + + @Nullable + @Override + public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) { + return null; + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleIcons.java b/simple_language_plugin/src/com/simpleplugin/SimpleIcons.java new file mode 100644 index 000000000..2719cf69e --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleIcons.java @@ -0,0 +1,9 @@ +package com.simpleplugin; + +import com.intellij.openapi.util.IconLoader; + +import javax.swing.*; + +public class SimpleIcons { + public static final Icon FILE = IconLoader.getIcon("/com/simpleplugin/icons/jar-gray.png"); +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleIdIndexer.java b/simple_language_plugin/src/com/simpleplugin/SimpleIdIndexer.java new file mode 100644 index 000000000..bfc0a75ac --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleIdIndexer.java @@ -0,0 +1,17 @@ +package com.simpleplugin; + +import com.intellij.lexer.Lexer; +import com.intellij.psi.impl.cache.impl.OccurrenceConsumer; +import com.intellij.psi.impl.cache.impl.id.LexerBasedIdIndexer; + +public class SimpleIdIndexer extends LexerBasedIdIndexer { + + public static Lexer createIndexingLexer(OccurrenceConsumer consumer) { + return new SimpleFilterLexer(new SimpleLexerAdapter(), consumer); + } + + @Override + public Lexer createLexer(final OccurrenceConsumer consumer) { + return createIndexingLexer(consumer); + } +} diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleLanguage.java b/simple_language_plugin/src/com/simpleplugin/SimpleLanguage.java new file mode 100644 index 000000000..425e59019 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleLanguage.java @@ -0,0 +1,11 @@ +package com.simpleplugin; + +import com.intellij.lang.Language; + +public class SimpleLanguage extends Language { + public static final SimpleLanguage INSTANCE = new SimpleLanguage(); + + private SimpleLanguage() { + super("Simple"); + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleLanguageCodeStyleSettingsProvider.java b/simple_language_plugin/src/com/simpleplugin/SimpleLanguageCodeStyleSettingsProvider.java new file mode 100644 index 000000000..5df02eb89 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleLanguageCodeStyleSettingsProvider.java @@ -0,0 +1,43 @@ +package com.simpleplugin; + +import com.intellij.lang.Language; +import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable; +import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider; +import org.jetbrains.annotations.NotNull; + +public class SimpleLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettingsProvider { + @NotNull + @Override + public Language getLanguage() { + return SimpleLanguage.INSTANCE; + } + + @Override + public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer, @NotNull SettingsType settingsType) { + if (settingsType == SettingsType.SPACING_SETTINGS) { + consumer.showStandardOptions("SPACE_AROUND_ASSIGNMENT_OPERATORS"); + consumer.renameStandardOption("SPACE_AROUND_ASSIGNMENT_OPERATORS", "Separator"); + } else if (settingsType == SettingsType.BLANK_LINES_SETTINGS) { + consumer.showStandardOptions("KEEP_BLANK_LINES_IN_CODE"); + } + } + + @Override + public String getCodeSample(@NotNull SettingsType settingsType) { + return "# You are reading the \".properties\" entry.\n" + + "! The exclamation mark can also mark text as comments.\n" + + "website = http://en.wikipedia.org/\n" + + "\n" + + "\n" + + "\n" + + "language = English\n" + + "# The backslash below tells the application to continue reading\n" + + "# the value onto the next line.\n" + + "message = Welcome to \\\n" + + " Wikipedia!\n" + + "# Add spaces to the key\n" + + "key\\ with\\ spaces = This is the value that could be looked up with the key \"key with spaces\".\n" + + "# Unicode\n" + + "tab : \\u0009"; + } +} diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleLexer.java b/simple_language_plugin/src/com/simpleplugin/SimpleLexer.java new file mode 100644 index 000000000..b18e92e45 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleLexer.java @@ -0,0 +1,509 @@ +/* The following code was generated by JFlex 1.4.3 on 02/09/15 10:04 AM */ + +package com.simpleplugin; + +import com.intellij.lexer.FlexLexer; +import com.intellij.psi.tree.IElementType; +import com.simpleplugin.psi.SimpleTypes; +import com.intellij.psi.TokenType; + + +/** + * This class is a scanner generated by + * JFlex 1.4.3 + * on 02/09/15 10:04 AM from the specification file + * /Users/vlad/src/SimplePlugin/src/com/simpleplugin/Simple.flex + */ +class SimpleLexer implements FlexLexer { + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int WAITING_VALUE = 2; + public static final int YYINITIAL = 0; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\0\1\3\1\1\1\0\1\6\1\2\22\0\1\5\1\7\1\0"+ + "\1\7\26\0\1\10\2\0\1\10\36\0\1\4\uffa3\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\2\0\1\1\1\2\1\3\1\4\1\5\1\6\1\7"+ + "\1\3\1\7\2\0\1\6"; + + private static int [] zzUnpackAction() { + int [] result = new int[14]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /** + * Translates a state to a row index in the transition table + */ + private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); + + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\11\0\22\0\33\0\44\0\55\0\66\0\77"+ + "\0\110\0\121\0\132\0\44\0\121\0\143"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[14]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackRowMap(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); + } + return j; + } + + /** + * The transition table of the DFA + */ + private static final int [] ZZ_TRANS = zzUnpackTrans(); + + private static final String ZZ_TRANS_PACKED_0 = + "\1\3\3\4\1\5\2\4\1\6\1\7\1\10\2\4"+ + "\1\11\1\12\2\13\2\10\1\3\3\0\1\14\2\0"+ + "\1\3\2\0\3\4\1\0\2\4\7\0\1\3\3\0"+ + "\1\6\2\0\6\6\11\0\1\10\2\0\1\10\1\15"+ + "\1\10\1\0\3\10\2\4\1\11\1\15\1\11\1\13"+ + "\4\10\1\16\6\10\1\0\2\4\1\13\1\0\2\13"+ + "\2\0\2\10\1\0\1\10\1\15\1\10\1\0\2\10"; + + private static int [] zzUnpackTrans() { + int [] result = new int[108]; + int offset = 0; + offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackTrans(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + value--; + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /* 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" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state aState + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\2\0\4\1\1\11\4\1\2\0\1\1"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[14]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAttribute(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + /** 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; + + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + + SimpleLexer(java.io.Reader in) { + this.zzReader = in; + } + + /** + * Creates a new scanner. + * There is also java.io.Reader version of this constructor. + * + * @param in the java.io.Inputstream to read input from. + */ + SimpleLexer(java.io.InputStream in) { + this(new java.io.InputStreamReader(in)); + } + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 36) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + 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 false, 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 pos 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 + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * 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()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); + + zzMarkedPos -= number; + } + + + /** + * Contains user EOF-code, which will be executed exactly once, + * when the end of file is reached + */ + private void zzDoEOF() { + if (!zzEOFDone) { + zzEOFDone = true; + + } + } + + + /** + * 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 + */ + public IElementType advance() throws java.io.IOException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + CharSequence zzBufferL = zzBuffer; + char[] zzBufferArrayL = zzBufferArray; + char [] zzCMapL = ZZ_CMAP; + + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) + zzInput = (zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++] : zzBufferL.charAt(zzCurrentPosL++)); + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = (zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++] : zzBufferL.charAt(zzCurrentPosL++)); + } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; + if (zzNext == -1) break zzForAction; + zzState = zzNext; + + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) break zzForAction; + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 6: + { yybegin(YYINITIAL); return SimpleTypes.VALUE; + } + case 8: break; + case 5: + { yybegin(WAITING_VALUE); return SimpleTypes.SEPARATOR; + } + case 9: break; + case 4: + { yybegin(YYINITIAL); return SimpleTypes.COMMENT; + } + case 10: break; + case 3: + { return TokenType.BAD_CHARACTER; + } + case 11: break; + case 2: + { yybegin(YYINITIAL); return TokenType.WHITE_SPACE; + } + case 12: break; + case 7: + { yybegin(WAITING_VALUE); return TokenType.WHITE_SPACE; + } + case 13: break; + case 1: + { yybegin(YYINITIAL); return SimpleTypes.KEY; + } + case 14: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + zzDoEOF(); + return null; + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleLexerAdapter.java b/simple_language_plugin/src/com/simpleplugin/SimpleLexerAdapter.java new file mode 100644 index 000000000..662acb59a --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleLexerAdapter.java @@ -0,0 +1,11 @@ +package com.simpleplugin; + +import com.intellij.lexer.FlexAdapter; + +import java.io.Reader; + +public class SimpleLexerAdapter extends FlexAdapter { + public SimpleLexerAdapter() { + super(new SimpleLexer((Reader) null)); + } +} diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleLineMarkerProvider.java b/simple_language_plugin/src/com/simpleplugin/SimpleLineMarkerProvider.java new file mode 100644 index 000000000..d6dc43d96 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleLineMarkerProvider.java @@ -0,0 +1,34 @@ +package com.simpleplugin; + +import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo; +import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider; +import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiLiteralExpression; +import com.simpleplugin.psi.SimpleProperty; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; + +public class SimpleLineMarkerProvider extends RelatedItemLineMarkerProvider { + @Override + protected void collectNavigationMarkers(@NotNull PsiElement element, Collection result) { + if (element instanceof PsiLiteralExpression) { + PsiLiteralExpression literalExpression = (PsiLiteralExpression) element; + String value = literalExpression.getValue() instanceof String ? (String)literalExpression.getValue() : null; + if (value != null && value.startsWith("simple"+":")) { + Project project = element.getProject(); + final List properties = SimpleUtil.findProperties(project, value.substring(7)); + if (properties.size() > 0) { + NavigationGutterIconBuilder builder = + NavigationGutterIconBuilder.create(SimpleIcons.FILE). + setTargets(properties). + setTooltipText("Navigate to a simple property"); + result.add(builder.createLineMarkerInfo(element)); + } + } + } + } +} diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleParserDefinition.java b/simple_language_plugin/src/com/simpleplugin/SimpleParserDefinition.java new file mode 100644 index 000000000..c9de1df95 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleParserDefinition.java @@ -0,0 +1,69 @@ +package com.simpleplugin; + +import com.intellij.lang.ASTNode; +import com.intellij.lang.Language; +import com.intellij.lang.ParserDefinition; +import com.intellij.lang.PsiParser; +import com.intellij.lexer.Lexer; +import com.intellij.openapi.project.Project; +import com.intellij.psi.FileViewProvider; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.TokenType; +import com.intellij.psi.tree.IFileElementType; +import com.intellij.psi.tree.TokenSet; +import com.simpleplugin.parser.SimpleParser; +import com.simpleplugin.psi.SimpleFile; +import com.simpleplugin.psi.SimpleTypes; +import org.jetbrains.annotations.NotNull; + +public class SimpleParserDefinition implements ParserDefinition{ + public static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE); + public static final TokenSet COMMENTS = TokenSet.create(SimpleTypes.COMMENT); + + public static final IFileElementType FILE = new IFileElementType(Language.findInstance(SimpleLanguage.class)); + + @NotNull + @Override + public Lexer createLexer(Project project) { + return new SimpleLexerAdapter(); + } + + @NotNull + public TokenSet getWhitespaceTokens() { + return WHITE_SPACES; + } + + @NotNull + public TokenSet getCommentTokens() { + return COMMENTS; + } + + @NotNull + public TokenSet getStringLiteralElements() { + return TokenSet.EMPTY; + } + + @NotNull + public PsiParser createParser(final Project project) { + return new SimpleParser(); + } + + @Override + public IFileElementType getFileNodeType() { + return FILE; + } + + public PsiFile createFile(FileViewProvider viewProvider) { + return new SimpleFile(viewProvider); + } + + public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) { + return SpaceRequirements.MAY; + } + + @NotNull + public PsiElement createElement(ASTNode node) { + return SimpleTypes.Factory.createElement(node); + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleRefactoringSupportProvider.java b/simple_language_plugin/src/com/simpleplugin/SimpleRefactoringSupportProvider.java new file mode 100644 index 000000000..8040801d7 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleRefactoringSupportProvider.java @@ -0,0 +1,12 @@ +package com.simpleplugin; + +import com.intellij.lang.refactoring.RefactoringSupportProvider; +import com.intellij.psi.PsiElement; +import com.simpleplugin.psi.SimpleProperty; + +public class SimpleRefactoringSupportProvider extends RefactoringSupportProvider { + @Override + public boolean isMemberInplaceRenameAvailable(PsiElement element, PsiElement context) { + return element instanceof SimpleProperty; + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleReference.java b/simple_language_plugin/src/com/simpleplugin/SimpleReference.java new file mode 100644 index 000000000..cbb9b295d --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleReference.java @@ -0,0 +1,58 @@ +package com.simpleplugin; + +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.simpleplugin.psi.SimpleProperty; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class SimpleReference extends PsiReferenceBase implements PsiPolyVariantReference { + private String key; + + public SimpleReference(@NotNull PsiElement element, TextRange textRange) { + super(element, textRange); + key = element.getText().substring(textRange.getStartOffset(), textRange.getEndOffset()); + } + + @NotNull + @Override + public ResolveResult[] multiResolve(boolean incompleteCode) { + Project project = myElement.getProject(); + final List properties = SimpleUtil.findProperties(project, key); + List results = new ArrayList(); + for (SimpleProperty property : properties) { + results.add(new PsiElementResolveResult(property)); + } + return results.toArray(new ResolveResult[results.size()]); + } + + @Nullable + @Override + public PsiElement resolve() { + ResolveResult[] resolveResults = multiResolve(false); + return resolveResults.length == 1 ? resolveResults[0].getElement() : null; + } + + @NotNull + @Override + public Object[] getVariants() { + Project project = myElement.getProject(); + List properties = SimpleUtil.findProperties(project); + List variants = new ArrayList(); + for (final SimpleProperty property : properties) { + if (property.getKey() != null && property.getKey().length() > 0) { + variants.add(LookupElementBuilder.create(property). + withIcon(SimpleIcons.FILE). + withTypeText(property.getContainingFile().getName()) + ); + } + } + return variants.toArray(); + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleReferenceContributor.java b/simple_language_plugin/src/com/simpleplugin/SimpleReferenceContributor.java new file mode 100644 index 000000000..99806e74f --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleReferenceContributor.java @@ -0,0 +1,26 @@ +package com.simpleplugin; + +import com.intellij.openapi.util.TextRange; +import com.intellij.patterns.PlatformPatterns; +import com.intellij.psi.*; +import com.intellij.util.ProcessingContext; +import org.jetbrains.annotations.NotNull; + +public class SimpleReferenceContributor extends PsiReferenceContributor { + @Override + public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) { + registrar.registerReferenceProvider(PlatformPatterns.psiElement(PsiLiteralExpression.class), + new PsiReferenceProvider() { + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + PsiLiteralExpression literalExpression = (PsiLiteralExpression) element; + String value = literalExpression.getValue() instanceof String ? (String)literalExpression.getValue() : null; + if (value != null && value.startsWith("simple"+":")) { + return new PsiReference[]{new SimpleReference(element, new TextRange(8, value.length() + 1))}; + } + return PsiReference.EMPTY_ARRAY; + } + }); + } +} diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleStructureViewElement.java b/simple_language_plugin/src/com/simpleplugin/SimpleStructureViewElement.java new file mode 100644 index 000000000..29ba22956 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleStructureViewElement.java @@ -0,0 +1,72 @@ +package com.simpleplugin; + +import com.intellij.ide.structureView.StructureViewTreeElement; +import com.intellij.ide.util.treeView.smartTree.SortableTreeElement; +import com.intellij.ide.util.treeView.smartTree.TreeElement; +import com.intellij.navigation.ItemPresentation; +import com.intellij.navigation.NavigationItem; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiNamedElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.simpleplugin.psi.SimpleFile; +import com.simpleplugin.psi.SimpleProperty; + +import java.util.ArrayList; +import java.util.List; + +public class SimpleStructureViewElement implements StructureViewTreeElement, SortableTreeElement { + private PsiElement element; + + public SimpleStructureViewElement(PsiElement element) { + this.element = element; + } + + @Override + public Object getValue() { + return element; + } + + @Override + public void navigate(boolean requestFocus) { + if (element instanceof NavigationItem) { + ((NavigationItem) element).navigate(requestFocus); + } + } + + @Override + public boolean canNavigate() { + return element instanceof NavigationItem && + ((NavigationItem)element).canNavigate(); + } + + @Override + public boolean canNavigateToSource() { + return element instanceof NavigationItem && + ((NavigationItem)element).canNavigateToSource(); + } + + @Override + public String getAlphaSortKey() { + return element instanceof PsiNamedElement ? ((PsiNamedElement) element).getName() : null; + } + + @Override + public ItemPresentation getPresentation() { + return element instanceof NavigationItem ? + ((NavigationItem) element).getPresentation() : null; + } + + @Override + public TreeElement[] getChildren() { + if (element instanceof SimpleFile) { + SimpleProperty[] properties = PsiTreeUtil.getChildrenOfType(element, SimpleProperty.class); + List treeElements = new ArrayList(properties.length); + for (SimpleProperty property : properties) { + treeElements.add(new SimpleStructureViewElement(property)); + } + return treeElements.toArray(new TreeElement[treeElements.size()]); + } else { + return EMPTY_ARRAY; + } + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleStructureViewFactory.java b/simple_language_plugin/src/com/simpleplugin/SimpleStructureViewFactory.java new file mode 100644 index 000000000..937fe85a6 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleStructureViewFactory.java @@ -0,0 +1,24 @@ +package com.simpleplugin; + +import com.intellij.ide.structureView.StructureViewBuilder; +import com.intellij.ide.structureView.StructureViewModel; +import com.intellij.ide.structureView.TreeBasedStructureViewBuilder; +import com.intellij.lang.PsiStructureViewFactory; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class SimpleStructureViewFactory implements PsiStructureViewFactory { + @Nullable + @Override + public StructureViewBuilder getStructureViewBuilder(final PsiFile psiFile) { + return new TreeBasedStructureViewBuilder() { + @NotNull + @Override + public StructureViewModel createStructureViewModel(@Nullable Editor editor) { + return new SimpleStructureViewModel(psiFile); + } + }; + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleStructureViewModel.java b/simple_language_plugin/src/com/simpleplugin/SimpleStructureViewModel.java new file mode 100644 index 000000000..3d2318087 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleStructureViewModel.java @@ -0,0 +1,32 @@ +package com.simpleplugin; + +import com.intellij.ide.structureView.StructureViewModel; +import com.intellij.ide.structureView.StructureViewModelBase; +import com.intellij.ide.structureView.StructureViewTreeElement; +import com.intellij.ide.util.treeView.smartTree.Sorter; +import com.intellij.psi.PsiFile; +import com.simpleplugin.psi.SimpleFile; +import org.jetbrains.annotations.NotNull; + +public class SimpleStructureViewModel extends StructureViewModelBase implements + StructureViewModel.ElementInfoProvider { + public SimpleStructureViewModel(PsiFile psiFile) { + super(psiFile, new SimpleStructureViewElement(psiFile)); + } + + @NotNull + public Sorter[] getSorters() { + return new Sorter[] {Sorter.ALPHA_SORTER}; + } + + + @Override + public boolean isAlwaysShowsPlus(StructureViewTreeElement element) { + return false; + } + + @Override + public boolean isAlwaysLeaf(StructureViewTreeElement element) { + return element instanceof SimpleFile; + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleSyntaxHighlighter.java b/simple_language_plugin/src/com/simpleplugin/SimpleSyntaxHighlighter.java new file mode 100644 index 000000000..530581d58 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleSyntaxHighlighter.java @@ -0,0 +1,52 @@ +package com.simpleplugin; + +import com.intellij.lexer.Lexer; +import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; +import com.intellij.openapi.editor.HighlighterColors; +import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.fileTypes.SyntaxHighlighterBase; +import com.intellij.psi.TokenType; +import com.intellij.psi.tree.IElementType; +import com.simpleplugin.psi.SimpleTypes; +import org.jetbrains.annotations.NotNull; + +import static com.intellij.openapi.editor.colors.TextAttributesKey.createTextAttributesKey; + +public class SimpleSyntaxHighlighter extends SyntaxHighlighterBase { + public static final TextAttributesKey SEPARATOR = createTextAttributesKey("SIMPLE_SEPARATOR", DefaultLanguageHighlighterColors.OPERATION_SIGN); + public static final TextAttributesKey KEY = createTextAttributesKey("SIMPLE_KEY", DefaultLanguageHighlighterColors.KEYWORD); + public static final TextAttributesKey VALUE = createTextAttributesKey("SIMPLE_VALUE", DefaultLanguageHighlighterColors.STRING); + public static final TextAttributesKey COMMENT = createTextAttributesKey("SIMPLE_COMMENT", DefaultLanguageHighlighterColors.LINE_COMMENT); + public static final TextAttributesKey BAD_CHARACTER = createTextAttributesKey("SIMPLE_BAD_CHARACTER", HighlighterColors.BAD_CHARACTER); + + private static final TextAttributesKey[] BAD_CHAR_KEYS = new TextAttributesKey[]{BAD_CHARACTER}; + private static final TextAttributesKey[] SEPARATOR_KEYS = new TextAttributesKey[]{SEPARATOR}; + private static final TextAttributesKey[] KEY_KEYS = new TextAttributesKey[]{KEY}; + private static final TextAttributesKey[] VALUE_KEYS = new TextAttributesKey[]{VALUE}; + private static final TextAttributesKey[] COMMENT_KEYS = new TextAttributesKey[]{COMMENT}; + private static final TextAttributesKey[] EMPTY_KEYS = new TextAttributesKey[0]; + + @NotNull + @Override + public Lexer getHighlightingLexer() { + return new SimpleLexerAdapter(); + } + + @NotNull + @Override + public TextAttributesKey[] getTokenHighlights(IElementType tokenType) { + if (tokenType.equals(SimpleTypes.SEPARATOR)) { + return SEPARATOR_KEYS; + } else if (tokenType.equals(SimpleTypes.KEY)) { + return KEY_KEYS; + } else if (tokenType.equals(SimpleTypes.VALUE)) { + return VALUE_KEYS; + } else if (tokenType.equals(SimpleTypes.COMMENT)) { + return COMMENT_KEYS; + } else if (tokenType.equals(TokenType.BAD_CHARACTER)) { + return BAD_CHAR_KEYS; + } else { + return EMPTY_KEYS; + } + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleSyntaxHighlighterFactory.java b/simple_language_plugin/src/com/simpleplugin/SimpleSyntaxHighlighterFactory.java new file mode 100644 index 000000000..e3a6fe428 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleSyntaxHighlighterFactory.java @@ -0,0 +1,15 @@ +package com.simpleplugin; + +import com.intellij.openapi.fileTypes.SyntaxHighlighter; +import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +public class SimpleSyntaxHighlighterFactory extends SyntaxHighlighterFactory { + @NotNull + @Override + public SyntaxHighlighter getSyntaxHighlighter(Project project, VirtualFile virtualFile) { + return new SimpleSyntaxHighlighter(); + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleTodoIndexer.java b/simple_language_plugin/src/com/simpleplugin/SimpleTodoIndexer.java new file mode 100644 index 000000000..505c0acce --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleTodoIndexer.java @@ -0,0 +1,12 @@ +package com.simpleplugin; + +import com.intellij.lexer.Lexer; +import com.intellij.psi.impl.cache.impl.OccurrenceConsumer; +import com.intellij.psi.impl.cache.impl.todo.LexerBasedTodoIndexer; + +public class SimpleTodoIndexer extends LexerBasedTodoIndexer { + @Override + public Lexer createLexer(OccurrenceConsumer consumer) { + return SimpleIdIndexer.createIndexingLexer(consumer); + } +} diff --git a/simple_language_plugin/src/com/simpleplugin/SimpleUtil.java b/simple_language_plugin/src/com/simpleplugin/SimpleUtil.java new file mode 100644 index 000000000..c2bb98218 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/SimpleUtil.java @@ -0,0 +1,57 @@ +package com.simpleplugin; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.search.FileTypeIndex; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.indexing.FileBasedIndex; +import com.simpleplugin.psi.SimpleFile; +import com.simpleplugin.psi.SimpleProperty; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class SimpleUtil { + public static List findProperties(Project project, String key) { + List result = null; + Collection virtualFiles = FileBasedIndex.getInstance().getContainingFiles(FileTypeIndex.NAME, SimpleFileType.INSTANCE, + GlobalSearchScope.allScope(project)); + for (VirtualFile virtualFile : virtualFiles) { + SimpleFile simpleFile = (SimpleFile) PsiManager.getInstance(project).findFile(virtualFile); + if (simpleFile != null) { + SimpleProperty[] properties = PsiTreeUtil.getChildrenOfType(simpleFile, SimpleProperty.class); + if (properties != null) { + for (SimpleProperty property : properties) { + if (key.equals(property.getKey())) { + if (result == null) { + result = new ArrayList(); + } + result.add(property); + } + } + } + } + } + return result != null ? result : Collections.emptyList(); + } + + public static List findProperties(Project project) { + List result = new ArrayList(); + Collection virtualFiles = FileBasedIndex.getInstance().getContainingFiles(FileTypeIndex.NAME, SimpleFileType.INSTANCE, + GlobalSearchScope.allScope(project)); + for (VirtualFile virtualFile : virtualFiles) { + SimpleFile simpleFile = (SimpleFile) PsiManager.getInstance(project).findFile(virtualFile); + if (simpleFile != null) { + SimpleProperty[] properties = PsiTreeUtil.getChildrenOfType(simpleFile, SimpleProperty.class); + if (properties != null) { + Collections.addAll(result, properties); + } + } + } + return result; + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/icons/jar-gray.png b/simple_language_plugin/src/com/simpleplugin/icons/jar-gray.png new file mode 100644 index 000000000..4760e60a0 Binary files /dev/null and b/simple_language_plugin/src/com/simpleplugin/icons/jar-gray.png differ diff --git a/simple_language_plugin/src/com/simpleplugin/psi/SimpleElementFactory.java b/simple_language_plugin/src/com/simpleplugin/psi/SimpleElementFactory.java new file mode 100644 index 000000000..91e10ba09 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/psi/SimpleElementFactory.java @@ -0,0 +1,29 @@ +package com.simpleplugin.psi; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFileFactory; +import com.simpleplugin.SimpleFileType; + +public class SimpleElementFactory { + public static SimpleProperty createProperty(Project project, String name, String value) { + final SimpleFile file = createFile(project, name + " = " + value); + return (SimpleProperty) file.getFirstChild(); + } + + public static SimpleProperty createProperty(Project project, String name) { + final SimpleFile file = createFile(project, name); + return (SimpleProperty) file.getFirstChild(); + } + + public static PsiElement createCRLF(Project project) { + final SimpleFile file = createFile(project, "\n"); + return file.getFirstChild(); + } + + public static SimpleFile createFile(Project project, String text) { + String name = "dummy.simple"; + return (SimpleFile) PsiFileFactory.getInstance(project). + createFileFromText(name, SimpleFileType.INSTANCE, text); + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/psi/SimpleElementType.java b/simple_language_plugin/src/com/simpleplugin/psi/SimpleElementType.java new file mode 100644 index 000000000..34e5c3464 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/psi/SimpleElementType.java @@ -0,0 +1,12 @@ +package com.simpleplugin.psi; + +import com.intellij.psi.tree.IElementType; +import com.simpleplugin.SimpleLanguage; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class SimpleElementType extends IElementType { + public SimpleElementType(@NotNull @NonNls String debugName) { + super(debugName, SimpleLanguage.INSTANCE); + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/psi/SimpleFile.java b/simple_language_plugin/src/com/simpleplugin/psi/SimpleFile.java new file mode 100644 index 000000000..21c8adc3b --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/psi/SimpleFile.java @@ -0,0 +1,32 @@ +package com.simpleplugin.psi; + +import com.intellij.extapi.psi.PsiFileBase; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.psi.FileViewProvider; +import com.simpleplugin.SimpleFileType; +import com.simpleplugin.SimpleLanguage; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +public class SimpleFile extends PsiFileBase { + public SimpleFile(@NotNull FileViewProvider viewProvider) { + super(viewProvider, SimpleLanguage.INSTANCE); + } + + @NotNull + @Override + public FileType getFileType() { + return SimpleFileType.INSTANCE; + } + + @Override + public String toString() { + return "Simple File"; + } + + @Override + public Icon getIcon(int flags) { + return super.getIcon(flags); + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/psi/SimpleNamedElement.java b/simple_language_plugin/src/com/simpleplugin/psi/SimpleNamedElement.java new file mode 100644 index 000000000..8c4d9260c --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/psi/SimpleNamedElement.java @@ -0,0 +1,6 @@ +package com.simpleplugin.psi; + +import com.intellij.psi.PsiNameIdentifierOwner; + +public interface SimpleNamedElement extends PsiNameIdentifierOwner { +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/psi/SimpleTokenType.java b/simple_language_plugin/src/com/simpleplugin/psi/SimpleTokenType.java new file mode 100644 index 000000000..6bdb585b4 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/psi/SimpleTokenType.java @@ -0,0 +1,17 @@ +package com.simpleplugin.psi; + +import com.intellij.psi.tree.IElementType; +import com.simpleplugin.SimpleLanguage; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class SimpleTokenType extends IElementType { + public SimpleTokenType(@NotNull @NonNls String debugName) { + super(debugName, SimpleLanguage.INSTANCE); + } + + @Override + public String toString() { + return "SimpleTokenType." + super.toString(); + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/psi/impl/SimpleNamedElementImpl.java b/simple_language_plugin/src/com/simpleplugin/psi/impl/SimpleNamedElementImpl.java new file mode 100644 index 000000000..dcb333a62 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/psi/impl/SimpleNamedElementImpl.java @@ -0,0 +1,12 @@ +package com.simpleplugin.psi.impl; + +import com.intellij.extapi.psi.ASTWrapperPsiElement; +import com.intellij.lang.ASTNode; +import com.simpleplugin.psi.SimpleNamedElement; +import org.jetbrains.annotations.NotNull; + +public abstract class SimpleNamedElementImpl extends ASTWrapperPsiElement implements SimpleNamedElement { + public SimpleNamedElementImpl(@NotNull ASTNode node) { + super(node); + } +} \ No newline at end of file diff --git a/simple_language_plugin/src/com/simpleplugin/psi/impl/SimplePsiImplUtil.java b/simple_language_plugin/src/com/simpleplugin/psi/impl/SimplePsiImplUtil.java new file mode 100644 index 000000000..3e58dc070 --- /dev/null +++ b/simple_language_plugin/src/com/simpleplugin/psi/impl/SimplePsiImplUtil.java @@ -0,0 +1,81 @@ +package com.simpleplugin.psi.impl; + +import com.intellij.lang.ASTNode; +import com.intellij.navigation.ItemPresentation; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.simpleplugin.SimpleIcons; +import com.simpleplugin.psi.SimpleElementFactory; +import com.simpleplugin.psi.SimpleProperty; +import com.simpleplugin.psi.SimpleTypes; +import org.jetbrains.annotations.Nullable; +import java.lang.String; + +import javax.swing.*; + +public class SimplePsiImplUtil { + public static String getKey(SimpleProperty element) { + ASTNode keyNode = element.getNode().findChildByType(SimpleTypes.KEY); + if (keyNode != null) { + // IMPORTANT: Convert embedded escaped spaces to simple spaces + return keyNode.getText().replaceAll("\\\\ "," "); + } else { + return null; + } + } + + public static String getValue(SimpleProperty element) { + ASTNode valueNode = element.getNode().findChildByType(SimpleTypes.VALUE); + if (valueNode != null) { + return valueNode.getText(); + } else { + return null; + } + } + + public static String getName(SimpleProperty element) { + return getKey(element); + } + + public static PsiElement setName(SimpleProperty element, String newName) { + ASTNode keyNode = element.getNode().findChildByType(SimpleTypes.KEY); + if (keyNode != null) { + SimpleProperty property = SimpleElementFactory.createProperty(element.getProject(), newName); + ASTNode newKeyNode = property.getFirstChild().getNode(); + element.getNode().replaceChild(keyNode, newKeyNode); + } + return element; + } + + public static PsiElement getNameIdentifier(SimpleProperty element) { + ASTNode keyNode = element.getNode().findChildByType(SimpleTypes.KEY); + if (keyNode != null) { + return keyNode.getPsi(); + } else { + return null; + } + } + + public static ItemPresentation getPresentation(final SimpleProperty element) { + return new ItemPresentation() { + @Nullable + @Override + public String getPresentableText() { + return element.getKey(); + } + + @Nullable + @Override + public String getLocationString() { + PsiFile containingFile = element.getContainingFile(); + return containingFile == null ? null : containingFile.getName(); + } + + @Nullable + @Override + public Icon getIcon(boolean unused) { + return SimpleIcons.FILE; + } + }; + } +} diff --git a/simple_language_plugin/testData/AnnotatorTestData.java b/simple_language_plugin/testData/AnnotatorTestData.java new file mode 100644 index 000000000..699bba52c --- /dev/null +++ b/simple_language_plugin/testData/AnnotatorTestData.java @@ -0,0 +1,7 @@ +public class Test { + public static void main(String[] args) { + System.out.println("simple:website"); + System.out.println("simple:key with spaces"); + System.out.println("simple:websit"); + } +} diff --git a/simple_language_plugin/testData/CompleteTestData.java b/simple_language_plugin/testData/CompleteTestData.java new file mode 100644 index 000000000..4a883daec --- /dev/null +++ b/simple_language_plugin/testData/CompleteTestData.java @@ -0,0 +1,5 @@ +public class Test { + public static void main(String[] args) { + System.out.println("simple:"); + } +} diff --git a/simple_language_plugin/testData/DefaultTestData.simple b/simple_language_plugin/testData/DefaultTestData.simple new file mode 100644 index 000000000..ebe624812 --- /dev/null +++ b/simple_language_plugin/testData/DefaultTestData.simple @@ -0,0 +1,14 @@ +# You are reading the ".properties" entry. +! The exclamation mark can also mark text as comments. +website = http://en.wikipedia.org/ + + +language = English +# The backslash below tells the application to continue reading +# the value onto the next line. +message = Welcome to \ + Wikipedia! +# Add spaces to the key +key\ with\ spaces = This is the value that could be looked up with the key "key with spaces". +# Unicode +tab : \u0009 diff --git a/simple_language_plugin/testData/FindUsagesTestData.java b/simple_language_plugin/testData/FindUsagesTestData.java new file mode 100644 index 000000000..401d8c782 --- /dev/null +++ b/simple_language_plugin/testData/FindUsagesTestData.java @@ -0,0 +1,5 @@ +public class Test { + public static void main(String[] args) { + System.out.println("simple:key with spaces"); + } +} diff --git a/simple_language_plugin/testData/FindUsagesTestData.simple b/simple_language_plugin/testData/FindUsagesTestData.simple new file mode 100644 index 000000000..2f31ab9e2 --- /dev/null +++ b/simple_language_plugin/testData/FindUsagesTestData.simple @@ -0,0 +1,13 @@ +# You are reading the ".properties" entry. +! The exclamation mark can also mark text as comments. +website = http://en.wikipedia.org/ + +language = English +# The backslash below tells the application to continue reading +# the value onto the next line. +message = Welcome to \ + Wikipedia! +# Add spaces to the key +key\ with\ spaces = This is the value that could be looked up with the key "key with spaces". +# Unicode +tab : \u0009 diff --git a/simple_language_plugin/testData/FoldingTestData.java b/simple_language_plugin/testData/FoldingTestData.java new file mode 100644 index 000000000..1920b5fae --- /dev/null +++ b/simple_language_plugin/testData/FoldingTestData.java @@ -0,0 +1,11 @@ +public class Test { + public static void main(String[] args) { + System.out.println("simple:website"); + } + public static void main1(String[] args) { + System.out.println("simple:key with spaces"); + } + public static void main2(String[] args) { + System.out.println("simple:message"); + } +} diff --git a/simple_language_plugin/testData/FormatterTestData.simple b/simple_language_plugin/testData/FormatterTestData.simple new file mode 100644 index 000000000..44a78fa68 --- /dev/null +++ b/simple_language_plugin/testData/FormatterTestData.simple @@ -0,0 +1,15 @@ +# You are reading the ".properties" entry. +! The exclamation mark can also mark text as comments. +website=http://en.wikipedia.org/ + + + +language= English +# The backslash below tells the application to continue reading +# the value onto the next line. +message = Welcome to \ + Wikipedia! +# Add spaces to the key +key\ with\ spaces = This is the value that could be looked up with the key "key with spaces". +# Unicode +tab :\u0009 diff --git a/simple_language_plugin/testData/ParsingTestData.simple b/simple_language_plugin/testData/ParsingTestData.simple new file mode 100644 index 000000000..e11fdcef3 --- /dev/null +++ b/simple_language_plugin/testData/ParsingTestData.simple @@ -0,0 +1,17 @@ +# You are reading the ".properties" entry. +! The exclamation mark can also mark text as comments. +website = http://en.wikipedia.org/ + +language = English +# The backslash below tells the application to continue reading +# the value onto the next line. +message = Welcome to \ + Wikipedia! +# Add spaces to the key +key\ with\ spaces = This is the value that could be looked up with the key "key with spaces". +# Unicode +tab : \u0009 +# test for illegal key attempt +key\ +with\ +endofline = test diff --git a/simple_language_plugin/testData/ParsingTestData.txt b/simple_language_plugin/testData/ParsingTestData.txt new file mode 100644 index 000000000..ce7aa544e --- /dev/null +++ b/simple_language_plugin/testData/ParsingTestData.txt @@ -0,0 +1,63 @@ +Simple File(0,492) + PsiComment(SimpleTokenType.COMMENT)('# You are reading the ".properties" entry.')(0,42) + PsiWhiteSpace('\n')(42,43) + PsiComment(SimpleTokenType.COMMENT)('! The exclamation mark can also mark text as comments.')(43,97) + PsiWhiteSpace('\n')(97,98) + SimplePropertyImpl(PROPERTY)(98,132) + PsiElement(SimpleTokenType.KEY)('website')(98,105) + PsiWhiteSpace(' ')(105,106) + PsiElement(SimpleTokenType.SEPARATOR)('=')(106,107) + PsiWhiteSpace(' ')(107,108) + PsiElement(SimpleTokenType.VALUE)('http://en.wikipedia.org/')(108,132) + PsiWhiteSpace('\n\n')(132,134) + SimplePropertyImpl(PROPERTY)(134,152) + PsiElement(SimpleTokenType.KEY)('language')(134,142) + PsiWhiteSpace(' ')(142,143) + PsiElement(SimpleTokenType.SEPARATOR)('=')(143,144) + PsiWhiteSpace(' ')(144,145) + PsiElement(SimpleTokenType.VALUE)('English')(145,152) + PsiWhiteSpace('\n')(152,153) + PsiComment(SimpleTokenType.COMMENT)('# The backslash below tells the application to continue reading')(153,216) + PsiWhiteSpace('\n')(216,217) + PsiComment(SimpleTokenType.COMMENT)('# the value onto the next line.')(217,248) + PsiWhiteSpace('\n')(248,249) + SimplePropertyImpl(PROPERTY)(249,292) + PsiElement(SimpleTokenType.KEY)('message')(249,256) + PsiWhiteSpace(' ')(256,257) + PsiElement(SimpleTokenType.SEPARATOR)('=')(257,258) + PsiWhiteSpace(' ')(258,259) + PsiElement(SimpleTokenType.VALUE)('Welcome to \\n Wikipedia!')(259,292) + PsiWhiteSpace('\n')(292,293) + PsiComment(SimpleTokenType.COMMENT)('# Add spaces to the key')(293,316) + PsiWhiteSpace('\n')(316,317) + SimplePropertyImpl(PROPERTY)(317,410) + PsiElement(SimpleTokenType.KEY)('key\ with\ spaces')(317,334) + PsiWhiteSpace(' ')(334,335) + PsiElement(SimpleTokenType.SEPARATOR)('=')(335,336) + PsiWhiteSpace(' ')(336,337) + PsiElement(SimpleTokenType.VALUE)('This is the value that could be looked up with the key "key with spaces".')(337,410) + PsiWhiteSpace('\n')(410,411) + PsiComment(SimpleTokenType.COMMENT)('# Unicode')(411,420) + PsiWhiteSpace('\n')(420,421) + SimplePropertyImpl(PROPERTY)(421,433) + PsiElement(SimpleTokenType.KEY)('tab')(421,424) + PsiWhiteSpace(' ')(424,425) + PsiElement(SimpleTokenType.SEPARATOR)(':')(425,426) + PsiWhiteSpace(' ')(426,427) + PsiElement(SimpleTokenType.VALUE)('\u0009')(427,433) + PsiWhiteSpace('\n')(433,434) + PsiComment(SimpleTokenType.COMMENT)('# test for illegal key attempt')(434,464) + PsiWhiteSpace('\n')(464,465) + SimplePropertyImpl(PROPERTY)(465,468) + PsiElement(SimpleTokenType.KEY)('key')(465,468) + PsiErrorElement:, SimpleTokenType.COMMENT, SimpleTokenType.CRLF or SimpleTokenType.SEPARATOR expected, got '\'(468,469) + PsiElement(BAD_CHARACTER)('\')(468,469) + PsiWhiteSpace('\n')(469,470) + PsiElement(SimpleTokenType.KEY)('with')(470,474) + PsiElement(BAD_CHARACTER)('\')(474,475) + PsiWhiteSpace('\n')(475,476) + PsiElement(SimpleTokenType.KEY)('endofline')(476,485) + PsiWhiteSpace(' ')(485,486) + PsiElement(SimpleTokenType.SEPARATOR)('=')(486,487) + PsiWhiteSpace(' ')(487,488) + PsiElement(SimpleTokenType.VALUE)('test')(488,492) diff --git a/simple_language_plugin/testData/ReferenceTestData.java b/simple_language_plugin/testData/ReferenceTestData.java new file mode 100644 index 000000000..384347eda --- /dev/null +++ b/simple_language_plugin/testData/ReferenceTestData.java @@ -0,0 +1,5 @@ +public class Test { + public static void main(String[] args) { + System.out.println("simple:website"); + } +} diff --git a/simple_language_plugin/testData/RenameTestData.java b/simple_language_plugin/testData/RenameTestData.java new file mode 100644 index 000000000..384347eda --- /dev/null +++ b/simple_language_plugin/testData/RenameTestData.java @@ -0,0 +1,5 @@ +public class Test { + public static void main(String[] args) { + System.out.println("simple:website"); + } +} diff --git a/simple_language_plugin/testData/RenameTestData.simple b/simple_language_plugin/testData/RenameTestData.simple new file mode 100644 index 000000000..31492ca75 --- /dev/null +++ b/simple_language_plugin/testData/RenameTestData.simple @@ -0,0 +1,13 @@ +# You are reading the ".properties" entry. +! The exclamation mark can also mark text as comments. +website = http://en.wikipedia.org/ + +language = English +# The backslash below tells the application to continue reading +# the value onto the next line. +message = Welcome to \ + Wikipedia! +# Add spaces to the key +key\ with\ spaces = This is the value that could be looked up with the key "key with spaces". +# Unicode +tab : \u0009 \ No newline at end of file diff --git a/simple_language_plugin/testData/RenameTestDataAfter.simple b/simple_language_plugin/testData/RenameTestDataAfter.simple new file mode 100644 index 000000000..71bf7bf73 --- /dev/null +++ b/simple_language_plugin/testData/RenameTestDataAfter.simple @@ -0,0 +1,13 @@ +# You are reading the ".properties" entry. +! The exclamation mark can also mark text as comments. +websiteUrl = http://en.wikipedia.org/ + +language = English +# The backslash below tells the application to continue reading +# the value onto the next line. +message = Welcome to \ + Wikipedia! +# Add spaces to the key +key\ with\ spaces = This is the value that could be looked up with the key "key with spaces". +# Unicode +tab : \u0009 \ No newline at end of file diff --git a/simple_language_plugin/tests/com/simpleplugin/SimpleCodeInsightTest.java b/simple_language_plugin/tests/com/simpleplugin/SimpleCodeInsightTest.java new file mode 100644 index 000000000..f7a703264 --- /dev/null +++ b/simple_language_plugin/tests/com/simpleplugin/SimpleCodeInsightTest.java @@ -0,0 +1,86 @@ +package com.simpleplugin; + +import com.intellij.codeInsight.completion.CompletionType; +import com.intellij.codeInsight.generation.actions.CommentByLineCommentAction; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess; +import com.intellij.psi.PsiElement; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import com.intellij.usageView.UsageInfo; +import com.simpleplugin.psi.SimpleProperty; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +public class SimpleCodeInsightTest extends LightCodeInsightFixtureTestCase { + @Override + protected void setUp() throws Exception { + VfsRootAccess.SHOULD_PERFORM_ACCESS_CHECK = false; // TODO: a workaround for v15 + super.setUp(); + } + + @Override + protected String getTestDataPath() { + return "code_samples/simple_language_plugin/testData"; + } + + public void testCompletion() { + myFixture.configureByFiles("CompleteTestData.java", "DefaultTestData.simple"); + myFixture.complete(CompletionType.BASIC, 1); + List strings = myFixture.getLookupElementStrings(); + assertTrue(strings.containsAll(Arrays.asList("key with spaces", "language", "message", "tab", "website"))); + assertEquals(5, strings.size()); + } + + public void testAnnotator() { + myFixture.configureByFiles("AnnotatorTestData.java", "DefaultTestData.simple"); + myFixture.checkHighlighting(false, false, true); + } + + public void testFormatter() { + myFixture.configureByFiles("FormatterTestData.simple"); + CodeStyleSettingsManager.getSettings(getProject()).SPACE_AROUND_ASSIGNMENT_OPERATORS = true; + CodeStyleSettingsManager.getSettings(getProject()).KEEP_BLANK_LINES_IN_CODE = 2; + new WriteCommandAction.Simple(getProject()) { + @Override + protected void run() throws Throwable { + CodeStyleManager.getInstance(getProject()).reformat(myFixture.getFile()); + } + }.execute(); + myFixture.checkResultByFile("DefaultTestData.simple"); + } + + public void testRename() { + myFixture.configureByFiles("RenameTestData.java", "RenameTestData.simple"); + myFixture.renameElementAtCaret("websiteUrl"); + myFixture.checkResultByFile("RenameTestData.simple", "RenameTestDataAfter.simple", false); + } + + public void testFolding() { + myFixture.configureByFiles("DefaultTestData.simple"); + myFixture.testFolding(getTestDataPath() + "/FoldingTestData.java"); + } + + public void testFindUsages() { + Collection usageInfos = myFixture.testFindUsages("FindUsagesTestData.simple", "FindUsagesTestData.java"); + assertEquals(1, usageInfos.size()); + } + + public void testCommenter() { + myFixture.configureByText(SimpleFileType.INSTANCE, "website = http://en.wikipedia.org/"); + CommentByLineCommentAction commentAction = new CommentByLineCommentAction(); + commentAction.actionPerformedImpl(getProject(), myFixture.getEditor()); + myFixture.checkResult("#website = http://en.wikipedia.org/"); + commentAction.actionPerformedImpl(getProject(), myFixture.getEditor()); + myFixture.checkResult("website = http://en.wikipedia.org/"); + } + + public void testReference() { + myFixture.configureByFiles("ReferenceTestData.java", "DefaultTestData.simple"); + PsiElement element = myFixture.getFile().findElementAt(myFixture.getCaretOffset()).getParent(); + assertEquals("http://en.wikipedia.org/", ((SimpleProperty) element.getReferences()[0].resolve()).getValue()); + } +} diff --git a/simple_language_plugin/tests/com/simpleplugin/SimpleParsingTest.java b/simple_language_plugin/tests/com/simpleplugin/SimpleParsingTest.java new file mode 100644 index 000000000..83119a1a6 --- /dev/null +++ b/simple_language_plugin/tests/com/simpleplugin/SimpleParsingTest.java @@ -0,0 +1,28 @@ +package com.simpleplugin; + +import com.intellij.testFramework.ParsingTestCase; + +public class SimpleParsingTest extends ParsingTestCase { + public SimpleParsingTest() { + super("", "simple", new SimpleParserDefinition()); + } + + public void testParsingTestData() { + doTest(true); + } + + @Override + protected String getTestDataPath() { + return "code_samples/simple_language_plugin/testData"; + } + + @Override + protected boolean skipSpaces() { + return false; + } + + @Override + protected boolean includeRanges() { + return true; + } +} diff --git a/tool_window/resources/META-INF/plugin.xml b/tool_window/resources/META-INF/plugin.xml new file mode 100644 index 000000000..332a2a997 --- /dev/null +++ b/tool_window/resources/META-INF/plugin.xml @@ -0,0 +1,33 @@ + + org.jetbrains.plugins.sample.ToolWindow + Tool Window + This sample plugin illustrates how to create your custom tool window. + 2.0 + YourCompany + + + most HTML tags may be used + ]]> + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tool_window/resources/myToolWindow/Calendar-icon.png b/tool_window/resources/myToolWindow/Calendar-icon.png new file mode 100644 index 000000000..5e4d507a7 Binary files /dev/null and b/tool_window/resources/myToolWindow/Calendar-icon.png differ diff --git a/tool_window/resources/myToolWindow/Time-icon.png b/tool_window/resources/myToolWindow/Time-icon.png new file mode 100644 index 000000000..b9cbf33cc Binary files /dev/null and b/tool_window/resources/myToolWindow/Time-icon.png differ diff --git a/tool_window/resources/myToolWindow/Time-zone-icon.png b/tool_window/resources/myToolWindow/Time-zone-icon.png new file mode 100644 index 000000000..63843d352 Binary files /dev/null and b/tool_window/resources/myToolWindow/Time-zone-icon.png differ diff --git a/tool_window/resources/myToolWindow/plus.png b/tool_window/resources/myToolWindow/plus.png new file mode 100644 index 000000000..f5b3c6e3a Binary files /dev/null and b/tool_window/resources/myToolWindow/plus.png differ diff --git a/tool_window/src/myToolWindow/MyToolWindow.form b/tool_window/src/myToolWindow/MyToolWindow.form new file mode 100644 index 000000000..515e60337 --- /dev/null +++ b/tool_window/src/myToolWindow/MyToolWindow.form @@ -0,0 +1,63 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/tool_window/src/myToolWindow/MyToolWindowFactory.java b/tool_window/src/myToolWindow/MyToolWindowFactory.java new file mode 100644 index 000000000..1082183c6 --- /dev/null +++ b/tool_window/src/myToolWindow/MyToolWindowFactory.java @@ -0,0 +1,79 @@ +package myToolWindow; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowFactory; +import com.intellij.ui.content.Content; +import com.intellij.ui.content.ContentFactory; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Calendar; + +/** + * Created by IntelliJ IDEA. + * User: Alexey.Chursin + * Date: Aug 25, 2010 + * Time: 2:09:00 PM + */ +public class MyToolWindowFactory implements ToolWindowFactory { + + private JButton refreshToolWindowButton; + private JButton hideToolWindowButton; + private JLabel currentDate; + private JLabel currentTime; + private JLabel timeZone; + private JPanel myToolWindowContent; + private ToolWindow myToolWindow; + + + public MyToolWindowFactory() { + hideToolWindowButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + myToolWindow.hide(null); + } + }); + refreshToolWindowButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + MyToolWindowFactory.this.currentDateTime(); + } + }); + } + + // Create the tool window content. + public void createToolWindowContent(Project project, ToolWindow toolWindow) { + myToolWindow = toolWindow; + this.currentDateTime(); + ContentFactory contentFactory = ContentFactory.SERVICE.getInstance(); + Content content = contentFactory.createContent(myToolWindowContent, "", false); + toolWindow.getContentManager().addContent(content); + + } + + public void currentDateTime() { + // Get current date and time + Calendar instance = Calendar.getInstance(); + currentDate.setText(String.valueOf(instance.get(Calendar.DAY_OF_MONTH)) + "/" + + String.valueOf(instance.get(Calendar.MONTH) + 1) + "/" + String.valueOf(instance.get(Calendar.YEAR))); + currentDate.setIcon(new ImageIcon(getClass().getResource("/myToolWindow/Calendar-icon.png"))); + int min = instance.get(Calendar.MINUTE); + String strMin; + if (min < 10) { + strMin = "0" + String.valueOf(min); + } else { + strMin = String.valueOf(min); + } + currentTime.setText(instance.get(Calendar.HOUR_OF_DAY) + ":" + strMin); + currentTime.setIcon(new ImageIcon(getClass().getResource("/myToolWindow/Time-icon.png"))); + // Get time zone + long gmt_Offset = instance.get(Calendar.ZONE_OFFSET); // offset from GMT in milliseconds + String str_gmt_Offset = String.valueOf(gmt_Offset / 3600000); + str_gmt_Offset = (gmt_Offset > 0) ? "GMT + " + str_gmt_Offset : "GMT - " + str_gmt_Offset; + timeZone.setText(str_gmt_Offset); + timeZone.setIcon(new ImageIcon(getClass().getResource("/myToolWindow/Time-zone-icon.png"))); + + + } + +} diff --git a/tree_structure_provider/resources/META-INF/plugin.xml b/tree_structure_provider/resources/META-INF/plugin.xml new file mode 100644 index 000000000..8115e55c1 --- /dev/null +++ b/tree_structure_provider/resources/META-INF/plugin.xml @@ -0,0 +1,30 @@ + + org.jetbrains.plugins.sample.TreeStructure + Tree Structure Provider Demo + 1.0 + JetBrains + + Tree Structure Provider Demo + + Initial commit + + + com.intellij.modules.lang + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tree_structure_provider/src/org/jetbrains/tutorials/tree/structure/TextOnlyTreeStructureProvider.java b/tree_structure_provider/src/org/jetbrains/tutorials/tree/structure/TextOnlyTreeStructureProvider.java new file mode 100644 index 000000000..58fb2b216 --- /dev/null +++ b/tree_structure_provider/src/org/jetbrains/tutorials/tree/structure/TextOnlyTreeStructureProvider.java @@ -0,0 +1,40 @@ +package org.jetbrains.tutorials.tree.structure; + +import com.intellij.ide.projectView.TreeStructureProvider; +import com.intellij.ide.projectView.ViewSettings; +import com.intellij.ide.projectView.impl.nodes.PsiFileNode; +import com.intellij.ide.util.treeView.AbstractTreeNode; +import com.intellij.openapi.fileTypes.PlainTextFileType; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * @author Anna Bulenkova + */ +public class TextOnlyTreeStructureProvider implements TreeStructureProvider { + @NotNull + @Override + public Collection modify(@NotNull AbstractTreeNode parent, @NotNull Collection children, ViewSettings settings) { + ArrayList nodes = new ArrayList(); + for (AbstractTreeNode child : children) { + if (child instanceof PsiFileNode) { + VirtualFile file = ((PsiFileNode) child).getVirtualFile(); + if (file != null && !file.isDirectory() && !(file.getFileType() instanceof PlainTextFileType)) { + continue; + } + } + nodes.add(child); + } + return nodes; + } + + @Nullable + @Override + public Object getData(Collection collection, String s) { + return null; + } +} \ No newline at end of file