Skip to content

Commit

Permalink
fix #8
Browse files Browse the repository at this point in the history
  • Loading branch information
anqiansong committed Jan 20, 2022
1 parent b46f76c commit daa4115
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 10 deletions.
7 changes: 6 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

group 'cn.xiaoheiban'
version '0.7.18'
version '1.0.0'

repositories {
mavenCentral()
Expand Down Expand Up @@ -35,6 +35,11 @@ intellij {
patchPluginXml {
sinceBuild '193.0'
changeNotes """
<h1># 2022-01-20(1.0.0)</h1>
<ul>
<li>Add completion keys</li>
<li>Support to go to declaration cross files</li>
</ul>
<h1># 2021-11-25(v0.7.18)</h1>
<ul>
<li>Fix duplicate routes error if there declared 'prefix' </li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
public class KeywordCompletionContributor extends CompletionContributor implements DumbAware {
private static final String[] keywords = new String[]{"syntax", "import", "map", "type", "bool", "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "float32", "float64", "complex64", "complex128", "string", "int", "uint", "uintptr", "byte", "rune",
"get", "head", "post", "put", "patch", "delete", "connect", "options", "trace", "title", "desc", "author", "email", "version", "summary", "title", "desc", "author", "email", "version", "summary",
"group", "jwt", "doc", "server", "service", "info", "handler", "middleware"};
"group", "jwt", "doc", "server", "service", "info", "handler", "middleware","jwtTransition","prefix","any"};

public KeywordCompletionContributor() {
for (String keyword : keywords) {
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/cn/xiaoheiban/language/ApiAnnotator.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.intellij.lang.annotation.Annotator;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import org.antlr.jetbrains.adapter.psi.ScopeNode;
import org.jetbrains.annotations.NotNull;

import java.util.List;
Expand Down Expand Up @@ -65,6 +66,8 @@ public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder hold
if (element.getText().contains(".")) {
return;
}


if (allNode == null) {
ApiRootNode root = ApiFile.getRoot(element);
if (root == null) {
Expand All @@ -77,8 +80,18 @@ public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder hold
holder.createInfoAnnotation(element, element.getText()).setTextAttributes(ApiSyntaxHighlighter.IDENTIFIER);
return;
}

Set<ApiRootNode> apiRootNode = ApiRootNode.getApiRootNode(element);
for (ApiRootNode node : apiRootNode) {
Map<IElementType, List<ASTNode>> allNode = node.getAllNode();
if (ApiRootNode.resolve(allNode, ApiParserDefinition.rule(ApiParser.RULE_structNameId), name)) {
holder.createInfoAnnotation(element, element.getText()).setTextAttributes(ApiSyntaxHighlighter.IDENTIFIER);
return;
}
}
holder.createErrorAnnotation(element, "can not resolve " + name);
}
}


}
3 changes: 2 additions & 1 deletion src/main/java/cn/xiaoheiban/psi/IReference.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public PsiElement resolve() {
ScopeNode scope = (ScopeNode) myElement.getContext();
if (scope == null) return null;

return scope.resolve(myElement);
PsiElement resolve = scope.resolve(myElement);
return resolve;
}

@Override
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/cn/xiaoheiban/psi/IdentifierPSINode.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ public PsiReference getReference() {
switch (((RuleIElementType) elType).getRuleIndex()) {
// 允许跳转到struct reference的规则
case ApiParser.RULE_referenceId:
return new StructReference(this);
StructReference reference = new StructReference(this);
return reference;

}
}
Expand Down
153 changes: 147 additions & 6 deletions src/main/java/cn/xiaoheiban/psi/nodes/ApiRootNode.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package cn.xiaoheiban.psi.nodes;

import cn.xiaoheiban.antlr4.ApiParser;
import cn.xiaoheiban.language.ApiFileType;
import cn.xiaoheiban.parser.ApiParserDefinition;
import cn.xiaoheiban.psi.ApiFile;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.containers.ArrayListSet;
import org.antlr.jetbrains.adapter.SymtabUtils;
import org.antlr.jetbrains.adapter.psi.ScopeNode;
import org.apache.commons.collections.map.HashedMap;
Expand Down Expand Up @@ -74,6 +80,16 @@ public static Map<IElementType, Set<ASTNode>> getAllDuplicateNode(Map<IElementTy
return ret;
}

public static Set<String> getImports(PsiElement element) {
List<ASTNode> nodes = ApiFile.findChildren(element, ApiParserDefinition.rule(ApiParser.RULE_importValue));
Set<String> set = new ArrayListSet<>();
for (ASTNode node : nodes) {
String text = node.getLastChildNode().getText();
set.add(text.replaceAll("\"", ""));
}
return set;
}

public Map<String, Set<StructNameNode>> getAllStructMap() {
Map<String, Set<StructNameNode>> ret = new HashedMap();
Set<ASTNode> nodeSet = new HashSet<>();
Expand Down Expand Up @@ -108,20 +124,145 @@ public Map<String, Set<StructNameNode>> getAllStructMap() {

@Override
public @Nullable PsiElement resolve(PsiNamedElement element) {
PsiElement psiElement = SymtabUtils.resolve(this, ApiParserDefinition.ELEMENT_FACTORY, element, "/api/apiBody/typeStatement/typeSingleSpec/typeAlias/structNameId/IDENT");
PsiElement resolve = resolve(this, element, "");
if (resolve != null) {
return resolve;
}
Project project = element.getProject();
Set<String> pathSet = getImports(this);
VirtualFile[] virtualFiles = ProjectRootManager.getInstance(project).getContentRoots();
for (VirtualFile virtualFile : virtualFiles) {
PsiDirectory directory = PsiManager.getInstance(project).findDirectory(virtualFile);
if (null == directory) {
continue;
}
PsiElement psiElement = resolve(directory, element, pathSet);
if (psiElement != null) {
return psiElement;
}
}
return null;
}

public static Set<ApiRootNode> getApiRootNode(PsiElement element) {
ApiRootNode root = ApiFile.getRoot(element);
if (root==null){
return new ArrayListSet<>();
}
Project project = element.getProject();
Set<String> pathSet = getImports(root);
VirtualFile[] virtualFiles = ProjectRootManager.getInstance(project).getContentRoots();
Set<ApiRootNode> set = new ArrayListSet<>();
for (VirtualFile virtualFile : virtualFiles) {
PsiDirectory directory = PsiManager.getInstance(project).findDirectory(virtualFile);
if (null == directory) {
continue;
}
List<ApiRootNode> apiRootNode = getApiRootNode(directory,pathSet);
for (ApiRootNode node : apiRootNode) {
set.add(node);
}
}
return set;
}

private static List<ApiRootNode> getApiRootNode(PsiDirectory directory,Set<String> pathSet) {
List<ApiRootNode> list = new ArrayList<>();
PsiFile[] files = directory.getFiles();
for (PsiFile file : files) {
if (!(file.getFileType() instanceof ApiFileType)) {
continue;
}
PsiElement[] children = file.getChildren();
for (PsiElement psi : children) {
if (!(psi instanceof ApiRootNode)) {
continue;
}
ApiRootNode apiRootNode = (ApiRootNode) (psi);
String filePath = apiRootNode.getContainingFile().getVirtualFile().getPath();
boolean contains = false;
for (String path : pathSet) {
if (filePath.endsWith(path)) {
contains = true;
break;
}
}
if (!contains){
continue;
}
list.add(apiRootNode);
}
}
PsiDirectory[] subdirectories = directory.getSubdirectories();
if (subdirectories.length == 0) {
return list;
}

for (PsiDirectory d : subdirectories) {
List<ApiRootNode> apiRootNode = getApiRootNode(d,pathSet);
list.addAll(apiRootNode);
}
return list;
}

private PsiElement resolve(PsiDirectory directory, PsiNamedElement element, Set<String> expectedPath) {
PsiFile[] files = directory.getFiles();
for (PsiFile file : files) {
if (!(file.getFileType() instanceof ApiFileType)) {
continue;
}
PsiElement[] children = file.getChildren();
for (PsiElement psi : children) {
if (!(psi instanceof ApiRootNode)) {
continue;
}
ApiRootNode apiRootNode = (ApiRootNode) (psi);
String filePath = apiRootNode.getContainingFile().getVirtualFile().getPath();
boolean contains = false;
for (String path : expectedPath) {
if (filePath.endsWith(path)) {
contains = true;
break;
}
}
if (!contains) {
continue;
}
PsiElement resolve = resolve(apiRootNode, element, "");
if (resolve != null) {
return resolve;
}
}
}
PsiDirectory[] subdirectories = directory.getSubdirectories();
if (subdirectories.length == 0) {
return null;
}

for (PsiDirectory d : subdirectories) {
PsiElement psiElement = resolve(d);
if (psiElement != null) {
return psiElement;
}
}
return null;
}

public @Nullable PsiElement resolve(ScopeNode scope, PsiNamedElement element, String basePath) {
PsiElement psiElement = SymtabUtils.resolve(scope, ApiParserDefinition.ELEMENT_FACTORY, element, basePath + "/api/apiBody/typeStatement/typeSingleSpec/typeAlias/structNameId/IDENT");
if (psiElement != null) {
return psiElement;
}
psiElement = SymtabUtils.resolve(this, ApiParserDefinition.ELEMENT_FACTORY, element, "/api/apiBody/typeStatement/typeSingleSpec/typeStruct/structType/structNameId/IDENT");
psiElement = SymtabUtils.resolve(scope, ApiParserDefinition.ELEMENT_FACTORY, element, basePath + "/api/apiBody/typeStatement/typeSingleSpec/typeStruct/structType/structNameId/IDENT");
if (psiElement != null) {
return psiElement;
}
psiElement = SymtabUtils.resolve(this, ApiParserDefinition.ELEMENT_FACTORY, element, "/api/apiBody/typeStatement/typeGroupSpec/typeGroupBody/typeGroupAlias/structNameId/IDENT");
psiElement = SymtabUtils.resolve(scope, ApiParserDefinition.ELEMENT_FACTORY, element, basePath + "/api/apiBody/typeStatement/typeGroupSpec/typeGroupBody/typeGroupAlias/structNameId/IDENT");
if (psiElement != null) {
return psiElement;
}

psiElement = SymtabUtils.resolve(this, ApiParserDefinition.ELEMENT_FACTORY, element, "/api/apiBody/typeStatement/typeGroupSpec/typeGroupBody/structType/structNameId/IDENT");
psiElement = SymtabUtils.resolve(scope, ApiParserDefinition.ELEMENT_FACTORY, element, basePath + "/api/apiBody/typeStatement/typeGroupSpec/typeGroupBody/structType/structNameId/IDENT");
return psiElement;
}
}

0 comments on commit daa4115

Please sign in to comment.