From b940673f47a3f102324f79e53cadc4fc111d083c Mon Sep 17 00:00:00 2001 From: breandan Date: Mon, 21 Dec 2015 23:35:54 -0500 Subject: [PATCH] Reference code-samples directly (as per DRY) --- Gemfile.lock | 22 +++ tutorials/build_system/prerequisites.md | 63 +------ .../code_style_settings.md | 109 +---------- .../custom_language_support/commenter.md | 39 +--- .../completion_contributor.md | 26 +-- .../find_usages_provider.md | 66 +------ .../folding_builder.md | 63 +------ .../custom_language_support/formatter.md | 96 +--------- .../go_to_symbol_contributor.md | 36 +--- .../grammar_and_parser.md | 58 +----- .../language_and_filetype.md | 83 +-------- .../lexer_and_parser_definition.md | 170 +----------------- .../line_marker_provider.md | 38 +--- .../psi_helper_and_utilities.md | 88 +-------- .../custom_language_support/quick_fix.md | 169 +---------------- .../reference_contributor.md | 129 +------------ .../structure_view_factory.md | 137 +------------- ...tax_highlighter_and_color_settings_page.md | 149 +-------------- .../completion_test.md | 33 +--- .../writing_tests_for_plugins/parsing_test.md | 31 +--- 20 files changed, 65 insertions(+), 1540 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index d2ca2ad2b..e80966a8a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -62,13 +62,33 @@ GEM mini_portile2 (~> 2.0.0.rc2) nokogiri (1.6.7.1-x64-mingw32) mini_portile2 (~> 2.0.0.rc2) + octopress (3.0.11) + jekyll (>= 2.0) + mercenary (~> 0.3.2) + octopress-deploy + octopress-escape-code (~> 2.0) + octopress-hooks (~> 2.0) + redcarpet (~> 3.0) + titlecase + octopress-code-highlighter (4.3.0) + jekyll (~> 3.0) + octopress-deploy (1.3.0) + colorator + octopress-escape-code (2.1.1) + jekyll (~> 3.0) + octopress-hooks (2.6.1) + jekyll (>= 2.0) + octopress-render-code (1.0.4) + octopress-code-highlighter (~> 4.2) rake (10.4.2) rb-fsevent (0.9.6) rb-inotify (0.9.5) ffi (>= 0.5.0) + redcarpet (3.3.3) robotex (1.0.0) safe_yaml (1.0.4) sass (3.4.20) + titlecase (0.1.1) trollop (2.1.2) PLATFORMS @@ -80,6 +100,8 @@ DEPENDENCIES jekyll-git_metadata! jekyll-redirect-from link-checker! + octopress (~> 3.0) + octopress-render-code rake rouge! diff --git a/tutorials/build_system/prerequisites.md b/tutorials/build_system/prerequisites.md index 2d9226fb2..7085f5793 100644 --- a/tutorials/build_system/prerequisites.md +++ b/tutorials/build_system/prerequisites.md @@ -78,68 +78,9 @@ Create the following directory structure: ![Gradle directory structure](img/gradle_directory_structure.png) -```java -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; +{% include_code gradle_plugin_demo/src/main/java/HelloAction.java %} -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()); - } -} -``` - -```xml - - org.jetbrains - gradle_plugin_demo - 0.0.1 - dummy - - - ]]> - - - ]]> - - - - - - - - - - - - - - - - - - - - - - - - - -``` +{% include_code gradle_plugin_demo/src/main/resources/META-INF/plugin.xml %} Add a new Gradle Run Configuration, configured like so: diff --git a/tutorials/custom_language_support/code_style_settings.md b/tutorials/custom_language_support/code_style_settings.md index 830973f0f..2d9c02c85 100644 --- a/tutorials/custom_language_support/code_style_settings.md +++ b/tutorials/custom_language_support/code_style_settings.md @@ -4,71 +4,11 @@ title: 16. Code Style Setting ### 16.1. Define code style settings -```java -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); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleCodeStyleSettings.java %} ### 16.2. Define code style settings provider -```java -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); - } - } -} -``` - +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleCodeStyleSettingsProvider.java %} ### 16.3. Register the code style settings provider @@ -78,50 +18,7 @@ public class SimpleCodeStyleSettingsProvider extends CodeStyleSettingsProvider { ### 16.4. Define language code style settings provider -```java -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"); - } else if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) { - consumer.showStandardOptions("KEEP_LINE_BREAKS"); - } - } - - @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" + - "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"; - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleLanguageCodeStyleSettingsProvider.java %} ### 16.5. Register the language code style settings provider diff --git a/tutorials/custom_language_support/commenter.md b/tutorials/custom_language_support/commenter.md index 107a7e89d..2fa4953be 100644 --- a/tutorials/custom_language_support/commenter.md +++ b/tutorials/custom_language_support/commenter.md @@ -6,44 +6,7 @@ A commenter allows user to comment the code at the cursor or selected code autom ### 17.1. Define a commenter -```java -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; - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleCommenter.java %} ### 17.2. Register the commenter diff --git a/tutorials/custom_language_support/completion_contributor.md b/tutorials/custom_language_support/completion_contributor.md index 9627d0364..ab218d923 100644 --- a/tutorials/custom_language_support/completion_contributor.md +++ b/tutorials/custom_language_support/completion_contributor.md @@ -9,31 +9,7 @@ The easiest way to provide completion is to use a completion contributor. Let's provide custom completion for values in property files. -```java -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")); - } - } - ); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleCompletionContributor.java %} ### 9.2. Register the completion contributor diff --git a/tutorials/custom_language_support/find_usages_provider.md b/tutorials/custom_language_support/find_usages_provider.md index bf17f5c0c..0e4c3e9fd 100644 --- a/tutorials/custom_language_support/find_usages_provider.md +++ b/tutorials/custom_language_support/find_usages_provider.md @@ -7,71 +7,7 @@ A scanner breaks the text into words, defines the context for each word and pass ### 11.1. Define a find usages provider -```java -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 ""; - } - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleFindUsagesProvider.java %} ### 11.2. Register the find usages provider diff --git a/tutorials/custom_language_support/folding_builder.md b/tutorials/custom_language_support/folding_builder.md index 77e384314..d26af4ab8 100644 --- a/tutorials/custom_language_support/folding_builder.md +++ b/tutorials/custom_language_support/folding_builder.md @@ -8,68 +8,7 @@ A folding builder helps you to fold the code regions and replace it with specifi Let's replace usages of properties with its values by default. -```java -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 = (String) literalExpression.getValue(); - if (value != null && value.startsWith("simple:")) { - Project project = literalExpression.getProject(); - final List properties = SimpleUtil.findProperties(project, value.substring(7)); - 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() { - return properties.get(0).getValue(); - } - }); - } - } - } - 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; - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleFoldingBuilder.java %} ### 12.2. Register the folding builder diff --git a/tutorials/custom_language_support/formatter.md b/tutorials/custom_language_support/formatter.md index dc13f3ba4..73ce9fd16 100644 --- a/tutorials/custom_language_support/formatter.md +++ b/tutorials/custom_language_support/formatter.md @@ -9,105 +9,13 @@ title: 15. Formatter The formatter uses the blocks to receive formatting rules for each PSI element. Our goal is to cover each PSI element with such block. Since each block builds own children blocks we can generate extra blocks or skip any PSI elements. -```java -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; - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleBlock.java %} ### 15.2. Define a formatting model builder Let's define a formatter which removes extra spaces except the single ones around the property separator. -```java -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; - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleFormattingModelBuilder.java %} ### 15.3. Register the formatter diff --git a/tutorials/custom_language_support/go_to_symbol_contributor.md b/tutorials/custom_language_support/go_to_symbol_contributor.md index 9a7841c38..1466a5b61 100644 --- a/tutorials/custom_language_support/go_to_symbol_contributor.md +++ b/tutorials/custom_language_support/go_to_symbol_contributor.md @@ -43,41 +43,7 @@ property ::= (KEY? SEPARATOR VALUE?) | KEY {mixin="com.simpleplugin.psi.impl.Sim ### 13.3. Define a go to symbol contributor -```java -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()]); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleChooseByNameContributor.java %} ### 13.4. Register the go to symbol contributor diff --git a/tutorials/custom_language_support/grammar_and_parser.md b/tutorials/custom_language_support/grammar_and_parser.md index 91f138a23..b94377170 100644 --- a/tutorials/custom_language_support/grammar_and_parser.md +++ b/tutorials/custom_language_support/grammar_and_parser.md @@ -4,69 +4,17 @@ title: 3. Grammar and Parser ### 3.1. Define a token type -```java -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(); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/psi/SimpleTokenType.java %} ### 3.2. Define an element type -```java -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); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/psi/SimpleElementType.java %} ### 3.3. Define grammar Define a grammar for the properties language with */com/simpleplugin/Simple.bnf* file. -```java -{ - 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" -} - -simpleFile ::= item_* - -private item_ ::= (property|COMMENT|CRLF) - -property ::= (KEY? SEPARATOR VALUE?) | KEY -``` +{% include_code simple_language_plugin/src/com/simpleplugin/Simple.bnf lang:java %} As you see a properties file can contain properties, comments and line breaks. diff --git a/tutorials/custom_language_support/language_and_filetype.md b/tutorials/custom_language_support/language_and_filetype.md index 45f69c3c7..72a9ad38b 100644 --- a/tutorials/custom_language_support/language_and_filetype.md +++ b/tutorials/custom_language_support/language_and_filetype.md @@ -5,19 +5,7 @@ title: 2. Language and File Type ### 2.1. Define a language -```java -package com.simpleplugin; - -import com.intellij.lang.Language; - -public class SimpleLanguage extends Language { - public static final SimpleLanguage INSTANCE = new SimpleLanguage(); - - private SimpleLanguage() { - super("Simple"); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/Simple.bnf lang:java %} ### 2.2. Define an icon @@ -25,78 +13,15 @@ Copy the [icon](https://raw.githubusercontent.com/cheptsov/SimplePlugin/master/src/com/simpleplugin/icons/jar-gray.png) to **com.simpleplugin.icons** package. -```java -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"); -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleIcons.java %} ### 2.3. Define a file type -```java -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; - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleFileType.java %} ### 2.4. Define a file type factory -```java -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"); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleFileTypeFactory.java %} ### 2.5. Register the file type factory diff --git a/tutorials/custom_language_support/lexer_and_parser_definition.md b/tutorials/custom_language_support/lexer_and_parser_definition.md index c3093b1d7..74271ae9a 100644 --- a/tutorials/custom_language_support/lexer_and_parser_definition.md +++ b/tutorials/custom_language_support/lexer_and_parser_definition.md @@ -9,54 +9,7 @@ The easiest way to create a lexer is to use [JFlex](http://jflex.de/) Define */com/simpleplugin/Simple.flex* file with rules for our lexer. -```java -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\\] | "\\"{CRLF} | "\\". - -%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} { yybegin(YYINITIAL); return SimpleTypes.CRLF; } - - {WHITE_SPACE}+ { yybegin(WAITING_VALUE); return TokenType.WHITE_SPACE; } - - {FIRST_VALUE_CHARACTER}{VALUE_CHARACTER}* { yybegin(YYINITIAL); return SimpleTypes.VALUE; } - -{CRLF} { yybegin(YYINITIAL); return SimpleTypes.CRLF; } - -{WHITE_SPACE}+ { yybegin(YYINITIAL); return TokenType.WHITE_SPACE; } - -. { return TokenType.BAD_CHARACTER; } -``` +{% include_code simple_language_plugin/src/com/simpleplugin/Simple.flex lang:java %} ### 4.2. Generate a lexer class @@ -71,130 +24,15 @@ After that the IDE will generate lexer: *com.simpleplugin.SimpleLexer*. ### 4.3. Define an adapter -```java -package com.simpleplugin; - -import com.intellij.lexer.FlexAdapter; - -import java.io.Reader; - -public class SimpleLexerAdapter extends FlexAdapter { - public SimpleLexerAdapter() { - super(new SimpleLexer((Reader) null)); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleLexerAdapter.java %} ### 4.4. Define a file -```java -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); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/psi/SimpleFile.java %} ### 4.5. Define a parser definition -```java -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); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleParserDefinition.java %} ### 4.6. Register the parser definition diff --git a/tutorials/custom_language_support/line_marker_provider.md b/tutorials/custom_language_support/line_marker_provider.md index de2a2b740..61cc60b40 100644 --- a/tutorials/custom_language_support/line_marker_provider.md +++ b/tutorials/custom_language_support/line_marker_provider.md @@ -9,43 +9,7 @@ These icons may provide navigation to related code. Let's annotate usages of our properties within Java code and provide navigation to the definition of these properties. -```java -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 = (String) literalExpression.getValue(); - 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)); - } - } - } - } -} -``` - +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleLineMarkerProvider.java %} ## More technical details for implementers diff --git a/tutorials/custom_language_support/psi_helper_and_utilities.md b/tutorials/custom_language_support/psi_helper_and_utilities.md index 732b3952d..84061381c 100644 --- a/tutorials/custom_language_support/psi_helper_and_utilities.md +++ b/tutorials/custom_language_support/psi_helper_and_utilities.md @@ -9,33 +9,7 @@ If we want to have custom methods in PSI classes we need to define them separate Let's define an utility class with these helper methods. -```java -package com.simpleplugin.psi.impl; - -import com.intellij.lang.ASTNode; -import com.simpleplugin.psi.SimpleProperty; -import com.simpleplugin.psi.SimpleTypes; - -public class SimplePsiImplUtil { - public static String getKey(SimpleProperty element) { - ASTNode keyNode = element.getNode().findChildByType(SimpleTypes.KEY); - if (keyNode != null) { - return keyNode.getText(); - } 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; - } - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/psi/impl/SimplePsiImplUtil.java %} ### 6.2. Update grammar and regenerate the parser @@ -75,65 +49,7 @@ After we made our changes to the grammar we can regenerate the parser and PSI cl Now we need an utility class to search PSI elements for defined properties over the project. We will use this utility later when implementing code assistance. -```java -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; - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleUtil.java %} ---------------- [Previous](syntax_highlighter_and_color_settings_page.md) diff --git a/tutorials/custom_language_support/quick_fix.md b/tutorials/custom_language_support/quick_fix.md index 715835092..29272ceef 100644 --- a/tutorials/custom_language_support/quick_fix.md +++ b/tutorials/custom_language_support/quick_fix.md @@ -9,180 +9,17 @@ Let's add a quick fix which helps to define an unresolved property from its usag ### 18.1. Update the element factory -```java -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); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/psi/SimpleElementFactory.java %} ### 18.2. Define an intention action The quick fix will create a property in the file chosen by user, and navigate to this property after creation. -```java -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.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()); - } - SimpleProperty property = SimpleElementFactory.createProperty(project, key, ""); - simpleFile.getNode().addChild(property.getNode()); - ((Navigatable) property.getLastChild().getNavigationElement()).navigate(true); - FileEditorManager.getInstance(project).getSelectedTextEditor().getCaretModel(). - moveCaretRelatively(2, 0, false, false, false); - } - }.execute(); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/CreatePropertyQuickFix.java %} ### 18.3. Update the annotator -```java -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 = (String) literalExpression.getValue(); - 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)); - } - } - } - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleAnnotator.java %} ### 18.4. Run the project diff --git a/tutorials/custom_language_support/reference_contributor.md b/tutorials/custom_language_support/reference_contributor.md index 090fea9cc..aa4a8ee1e 100644 --- a/tutorials/custom_language_support/reference_contributor.md +++ b/tutorials/custom_language_support/reference_contributor.md @@ -10,29 +10,9 @@ Resolving references means the ability to go from the usage of an element to the ### 10.1. Define a base named element class -```java -package com.simpleplugin.psi; +{% include_code simple_language_plugin/src/com/simpleplugin/psi/SimpleNamedElement.java %} -import com.intellij.psi.PsiNameIdentifierOwner; - -public interface SimpleNamedElement extends PsiNameIdentifierOwner { -} -``` - -```java -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); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/psi/impl/SimpleNamedElementImpl.java %} ### 10.2. Define helper methods for generated PSI elements @@ -100,100 +80,14 @@ property ::= (KEY? SEPARATOR VALUE?) | KEY {mixin="com.simpleplugin.psi.impl.Sim Now we need to define a reference class to resolve a property from it's usage. -```java -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(); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleReference.java %} ### 10.6. Define a reference contributor A reference contributor allows you to provide references from elements in other languages such as Java to elements in your language. Let's contribute a reference to each usage of a property. -```java -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(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 text = (String) literalExpression.getValue(); - if (text != null && text.startsWith("simple:")) { - return new PsiReference[]{new SimpleReference(element, new TextRange(8, text.length() + 1))}; - } - return new PsiReference[0]; - } - }); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleReferenceContributor.java %} ### 10.7. Register the reference contributor @@ -215,20 +109,7 @@ As you see the IDE now resolves the property and provides completion. To allow in-place refactoring we should specify it explicitly in a refactoring support provider. -```java -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; - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleRefactoringSupportProvider.java %} ### 10.10. Register the refactoring support provider diff --git a/tutorials/custom_language_support/structure_view_factory.md b/tutorials/custom_language_support/structure_view_factory.md index cac80cc4e..86118964f 100644 --- a/tutorials/custom_language_support/structure_view_factory.md +++ b/tutorials/custom_language_support/structure_view_factory.md @@ -7,146 +7,15 @@ A structure view factory allows to show the structure of any file in a *Structur ### 14.1. Define a structure view factory -```java -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); - } - }; - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleStructureViewFactory.java %} ### 14.2. Define a structure view model -```java -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; - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleStructureViewModel.java %} ### 14.3. Define a structure view element -```java -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; - } - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleStructureViewElement.java %} ### 14.4. Register the structure view factory diff --git a/tutorials/custom_language_support/syntax_highlighter_and_color_settings_page.md b/tutorials/custom_language_support/syntax_highlighter_and_color_settings_page.md index 9155e23d0..01930ef34 100644 --- a/tutorials/custom_language_support/syntax_highlighter_and_color_settings_page.md +++ b/tutorials/custom_language_support/syntax_highlighter_and_color_settings_page.md @@ -5,80 +5,11 @@ title: 5. Syntax Highlighter and Color Settings Page ### 5.1. Define a syntax highlighter -```java -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; - } - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleSyntaxHighlighter.java %} ### 5.2. Define a syntax highlighter factory -```java -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(); - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleSyntaxHighlighterFactory.java %} ### 5.3. Register the syntax highlighter factory @@ -92,81 +23,7 @@ public class SimpleSyntaxHighlighterFactory extends SyntaxHighlighterFactory { ### 5.5. Define a color settings page -```java -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"; - } -} -``` +{% include_code simple_language_plugin/src/com/simpleplugin/SimpleColorSettingsPage.java %} ### 5.6. Register the color settings page diff --git a/tutorials/writing_tests_for_plugins/completion_test.md b/tutorials/writing_tests_for_plugins/completion_test.md index e8ff0a9d8..bedd2ec64 100644 --- a/tutorials/writing_tests_for_plugins/completion_test.md +++ b/tutorials/writing_tests_for_plugins/completion_test.md @@ -27,40 +27,11 @@ tab : \u0009 Create one more file *CompleteTestData.java*. -```java -public class Test { - public static void main(String[] args) { - System.out.println("simple:"); - } -} -``` +{% include_code simple_language_plugin/testData/CompleteTestData.java %} ### 3.2. Define a test -```java -package com.simpleplugin; - -import com.intellij.codeInsight.completion.CompletionType; -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; - -import java.util.Arrays; -import java.util.List; - -public class SimpleCodeInsightTest extends LightCodeInsightFixtureTestCase { - @Override - protected String getTestDataPath() { - return "../../SimplePlugin/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()); - } -} -``` +{% include_code simple_language_plugin/tests/com/simpleplugin/SimpleCodeInsightTest.java %} ### 3.3. Run the test diff --git a/tutorials/writing_tests_for_plugins/parsing_test.md b/tutorials/writing_tests_for_plugins/parsing_test.md index febb09778..e40cfed9b 100644 --- a/tutorials/writing_tests_for_plugins/parsing_test.md +++ b/tutorials/writing_tests_for_plugins/parsing_test.md @@ -95,36 +95,7 @@ Simple File(0,433) ### 2.4. Define a parsing test -```java -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 "../../SimplePlugin/testData"; - } - - @Override - protected boolean skipSpaces() { - return false; - } - - @Override - protected boolean includeRanges() { - return true; - } -} -``` +{% include_code simple_language_plugin/tests/com/simpleplugin/SimpleParsingTest.java %} ### 2.5. Run the test