IntelliJ Platform SDK DevGuide

6. PSI Helpers and Utilities

6.1.

为生成的PSI元素定义辅助方法

如果我们想在PSI类中使用自定义方法,我们需要单独定义它们并要求Grammar-Kit将它们嵌入到生成的代码中.

让我们用这些辅助方法定义一个实用程序类.

package com.simpleplugin.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.navigation.ItemPresentation; import com.intellij.psi.*; import com.simpleplugin.SimpleIcons; import com.simpleplugin.psi.*; import org.jetbrains.annotations.Nullable; 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; } } }

请注意,上面代码中引用的SimpleProperty接口是由解析器生成的. 另请注意,getPresentableText中使用的element.getKey方法将不会被定义 - 它是由解析器生成的方法,我们将在下面修复它.

6.2.

更新语法并重新生成解析器

现在我们告诉通过psiImplUtilClass属性在语法文件中使用这个实用程序类.

要说明必须使用哪些PSI类的方法,我们为特定规则指定方法.

{ 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 {methods=[getKey getValue]}

在我们对语法进行更改后,我们可以重新生成解析器和PSI类.

6.3.

定义实用程序以搜索属性

现在我们需要一个实用程序类来搜索PSI元素以查找项目中已定义的属性.

我们稍后将在实现代码帮助时使用此实用程序.

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.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.indexing.FileBasedIndex; import com.simpleplugin.psi.*; import java.util.*; public class SimpleUtil { public static List<SimpleProperty> findProperties(Project project, String key) { List<SimpleProperty> result = null; Collection<VirtualFile> virtualFiles = FileTypeIndex.getFiles(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<SimpleProperty>(); } result.add(property); } } } } } return result != null ? result : Collections.<SimpleProperty>emptyList(); } public static List<SimpleProperty> findProperties(Project project) { List<SimpleProperty> result = new ArrayList<SimpleProperty>(); Collection<VirtualFile> virtualFiles = FileTypeIndex.getFiles(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; } }
Last modified: 8 May 2019