Skip to content

Commit

Permalink
feat: show simple graph of files in a package
Browse files Browse the repository at this point in the history
  • Loading branch information
u215942 committed Jun 26, 2019
1 parent fc97eeb commit 11f189b
Show file tree
Hide file tree
Showing 11 changed files with 351 additions and 10 deletions.
29 changes: 29 additions & 0 deletions src/ch/docksnet/rgraph/PsiUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

import ch.docksnet.rgraph.method.ClassFQN;
import ch.docksnet.rgraph.method.FieldFQN;
import ch.docksnet.rgraph.method.FileFQN;
import ch.docksnet.rgraph.method.MethodFQN;
import ch.docksnet.rgraph.method.PackageFQN;
import ch.docksnet.rgraph.method.PsiElementDispatcher;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
Expand All @@ -29,10 +31,13 @@
import com.intellij.psi.PsiAnonymousClass;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassInitializer;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.impl.file.PsiJavaDirectoryImpl;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.Nullable;

Expand Down Expand Up @@ -129,6 +134,10 @@ public static PsiClass getPsiClass(String classFQN, Project project) {
.projectScope(project));
}

public static PsiDirectory getPsiJavaDirectory(String packageFQN, Project project) {
return JavaPsiFacade.getInstance(project).findPackage("ch.sbb.aps.safetylogic.interfaces.l0").getDirectories()[0];
}

private static String getName(PsiClassInitializer psiClassInitializer) {
if (psiClassInitializer.getModifierList().hasModifierProperty("static")) {
return "[static init]";
Expand Down Expand Up @@ -176,6 +185,16 @@ public String processStaticInnerClass(PsiClass staticInnerClass) {
public String processEnum(PsiClass anEnum) {
return anEnum.getName();
}

@Override
public String processPackage(PsiJavaDirectoryImpl aPackage) {
return aPackage.getName();
}

@Override
public String processFile(PsiJavaFile aFile) {
return aFile.getName();
}
};

return psiElementDispatcher.dispatch(psiElement);
Expand Down Expand Up @@ -218,6 +237,16 @@ public String processStaticInnerClass(PsiClass staticInnerClass) {
public String processEnum(PsiClass anEnum) {
return ClassFQN.create(anEnum).getFQN();
}

@Override
public String processPackage(PsiJavaDirectoryImpl aPackage) {
return PackageFQN.create(aPackage).getFQN();
}

@Override
public String processFile(PsiJavaFile psiElement) {
return FileFQN.create(psiElement).getFQN();
}
};

return psiElementDispatcher.dispatch(psiElement);
Expand Down
5 changes: 5 additions & 0 deletions src/ch/docksnet/rgraph/ReferenceDiagramElementManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.file.PsiJavaDirectoryImpl;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.SimpleColoredText;
import org.jetbrains.annotations.Nullable;
Expand All @@ -44,6 +45,10 @@ public PsiElement findInDataContext(DataContext context) {
return CommonDataKeys.PSI_ELEMENT.getData(context);
}

if (CommonDataKeys.PSI_ELEMENT.getData(context) instanceof PsiJavaDirectoryImpl) {
return CommonDataKeys.PSI_ELEMENT.getData(context);
}

if (CommonDataKeys.PSI_FILE.getData(context) == null) {
return null;
}
Expand Down
10 changes: 8 additions & 2 deletions src/ch/docksnet/rgraph/ReferenceDiagramProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@

package ch.docksnet.rgraph;

import ch.docksnet.rgraph.directory.PackageReferenceDiagramDataModel;
import ch.docksnet.rgraph.method.MethodReferenceDiagramDataModel;
import ch.docksnet.rgraph.method.ReferenceDiagramColorManager;
import ch.docksnet.rgraph.method.ReferenceDiagramExtras;
import ch.docksnet.rgraph.method.ReferenceDiagramVfsResolver;
import ch.docksnet.rgraph.method.ReferenceUmlCategoryManager;
import com.intellij.diagram.BaseDiagramProvider;
import com.intellij.diagram.DiagramColorManager;
import com.intellij.diagram.DiagramDataModel;
import com.intellij.diagram.DiagramElementManager;
import com.intellij.diagram.DiagramNodeContentManager;
import com.intellij.diagram.DiagramPresentationModel;
Expand All @@ -33,6 +35,7 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.file.PsiJavaDirectoryImpl;
import org.intellij.lang.annotations.Pattern;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -67,7 +70,7 @@ public DiagramVfsResolver<PsiElement> getVfsResolver() {

@Override
public String getPresentableName() {
return "Method Reference Diagram";
return "Java Reference Diagram";
}

@NotNull
Expand All @@ -77,11 +80,14 @@ public DiagramExtras<PsiElement> getExtras() {
}

@Override
public MethodReferenceDiagramDataModel createDataModel(@NotNull Project project, @Nullable PsiElement
public DiagramDataModel createDataModel(@NotNull Project project, @Nullable PsiElement
psiElement, @Nullable VirtualFile virtualFile, DiagramPresentationModel model) {
if (psiElement instanceof PsiClass) {
return new MethodReferenceDiagramDataModel(project, (PsiClass) psiElement);
}
if (psiElement instanceof PsiJavaDirectoryImpl) {
return new PackageReferenceDiagramDataModel(project, (PsiJavaDirectoryImpl) psiElement);
}
return null;
}

Expand Down
204 changes: 204 additions & 0 deletions src/ch/docksnet/rgraph/directory/PackageReferenceDiagramDataModel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/*
* Copyright (C) 2019 Stefan Zeller
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package ch.docksnet.rgraph.directory;

import ch.docksnet.rgraph.PsiUtils;
import ch.docksnet.rgraph.ReferenceDiagramProvider;
import ch.docksnet.rgraph.method.MethodReferenceDiagramDataModel;
import ch.docksnet.rgraph.method.ReferenceNode;
import com.intellij.diagram.DiagramDataModel;
import com.intellij.diagram.DiagramEdge;
import com.intellij.diagram.DiagramNode;
import com.intellij.diagram.DiagramProvider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.SmartPointerManager;
import com.intellij.psi.SmartPsiElementPointer;
import com.intellij.psi.impl.file.PsiJavaDirectoryImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import static ch.docksnet.rgraph.PsiUtils.getFqn;

public class PackageReferenceDiagramDataModel extends DiagramDataModel<PsiElement> {

private final Map<String, SmartPsiElementPointer<PsiElement>> elementsAddedByUser = new HashMap();
private final Map<String, SmartPsiElementPointer<PsiElement>> elementsRemovedByUser = new HashMap();
private final Map<PsiElement, DiagramNode<PsiElement>> nodesPool = new HashMap<>();
private final SmartPointerManager spManager;

private final Collection<DiagramNode<PsiElement>> nodes = new HashSet<>();
private final Collection<DiagramEdge<PsiElement>> edges = new HashSet<>();

public PackageReferenceDiagramDataModel(Project project, PsiJavaDirectoryImpl directory) {
super(project, ReferenceDiagramProvider.getInstance());
this.spManager = SmartPointerManager.getInstance(getProject());
init(directory);
}

private void init(PsiJavaDirectoryImpl directory) {
for (PsiElement child : directory.getChildren()) {
if (child instanceof PsiJavaFile) {
this.elementsAddedByUser.put(getFqn(child), this.spManager.createSmartPsiElementPointer(child));
}
}
}

@NotNull
@Override
public Collection<? extends DiagramNode<PsiElement>> getNodes() {
if (this.nodes == null) {
throw new IllegalStateException("@NotNull method %s.%s must not return null");
} else {
return this.nodes;
}
}

@NotNull
@Override
public Collection<? extends DiagramEdge<PsiElement>> getEdges() {
if (this.edges == null) {
throw new IllegalStateException(String.format("@NotNull method %s.%s must not return null",
new Object[]{"com/intellij/uml/java/JavaUmlDataModel", "getEdges"}));
} else {
return this.edges;
}
}

@NotNull
@Override
public String getNodeName(DiagramNode<PsiElement> diagramNode) {
return PsiUtils.getPresentableName(diagramNode.getIdentifyingElement());
}

@Nullable
@Override
public DiagramNode<PsiElement> addElement(PsiElement psiElement) {
return null;
}

@Override
public void refreshDataModel() {
clearAll();
updateDataModel();
}

private void clearAll() {
this.nodes.clear();
this.edges.clear();
}

private synchronized void updateDataModel() {
DiagramProvider provider = getBuilder().getProvider();
Set<PsiElement> elements = getElements();

for (PsiElement element : elements) {
if (isAllowedToShow(element)) {
this.nodes.add(getReferenceNode(provider, element));
}
}
}

private Set<PsiElement> getElements() {
Set<PsiElement> result = new HashSet<>();

for (SmartPsiElementPointer<PsiElement> psiElementPointer : this.elementsAddedByUser.values()) {
PsiElement element = psiElementPointer.getElement();
result.add(element);
}

for (SmartPsiElementPointer<PsiElement> psiElementPointer : this.elementsRemovedByUser.values()) {
PsiElement element = psiElementPointer.getElement();
result.remove(element);
}

return result;
}

@NotNull
private ReferenceNode getReferenceNode(DiagramProvider provider, PsiElement element) {
if (this.nodesPool.containsKey(element)) {
return (ReferenceNode) this.nodesPool.get(element);
}
ReferenceNode node = new ReferenceNode(element, provider);
this.nodesPool.put(element, node);
return node;
}

private boolean isAllowedToShow(PsiElement element) {
return true;
}

@NotNull
@Override
public ModificationTracker getModificationTracker() {
return PsiManager.getInstance(getProject()).getModificationTracker();
}

@Override
public void dispose() {
}

@Override
public void rebuild(PsiElement element) {
super.rebuild(element);
this.elementsRemovedByUser.clear();
clearAll();
init((PsiJavaDirectoryImpl) element);
refreshDataModel();
}

@Override
public boolean hasElement(PsiElement element) {
return findNode(element) != null;
}

/**
* @param psiElement
* @return {@code true} if {@code nodes} contains {@code psiElement}.
*/
@Nullable
private DiagramNode<PsiElement> findNode(PsiElement psiElement) {
Iterator ptr = (new ArrayList(this.nodes)).iterator();

while (ptr.hasNext()) {
DiagramNode node = (DiagramNode) ptr.next();
String fqn = PsiUtils.getFqn((PsiElement) node.getIdentifyingElement());
if (fqn != null && fqn.equals(PsiUtils.getFqn(psiElement))) {
return node;
}
}
return null;
}

@Override
public boolean isPsiListener() {
return true;
}
}
6 changes: 5 additions & 1 deletion src/ch/docksnet/rgraph/method/ClassFQN.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ public static ClassFQN create(PsiClass psiClass) {
}

public static boolean isClassFQN(String string) {
return true;
String[] split = string.split("\\.");
if (Character.isUpperCase(split[split.length - 1].charAt(0))) {
return true;
}
return false;
}

public String getFQN() {
Expand Down
8 changes: 8 additions & 0 deletions src/ch/docksnet/rgraph/method/FileFQN.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ static FileFQN resolveHierarchically(PsiElement psiElement) {
return from((PsiJavaFile) psiJavaFile);
}

public static FileFQN create(PsiJavaFile psiJavaFile) {
return from(psiJavaFile);
}

boolean samePackage(FileFQN otherFile) {
return this.packageName.equals(otherFile.packageName);
}
Expand Down Expand Up @@ -81,4 +85,8 @@ public String toString() {
public PsiJavaFile getPsiJavaFile() {
return this.psiJavaFile;
}

public String getFQN() {
return this.toString();
}
}
Loading

0 comments on commit 11f189b

Please sign in to comment.