Skip to content

Commit 934d6f6

Browse files
committed
Improved the GotoRelated functionality
1 parent ad5b7fc commit 934d6f6

4 files changed

Lines changed: 139 additions & 16 deletions

File tree

.idea/dictionaries/patrick.xml

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/de/halirutan/mathematica/codeinsight/navigation/GotoSymbolItem.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,44 @@
2727
import org.jetbrains.annotations.Nullable;
2828

2929
/**
30+
* Provides a {@link GotoRelatedItem} that is useful to give information about the usage of a Mathematica symbol
31+
*
3032
* @author patrick (28.12.16).
3133
*/
3234
public class GotoSymbolItem extends GotoRelatedItem {
35+
3336
private final String myDescription;
34-
GotoSymbolItem(@NotNull PsiElement element, final String description) {
37+
private final String myContext;
38+
private final int myLineNumber;
39+
40+
/**
41+
* Create an entry with description text
42+
* @param element {@link PsiElement} to navigate to
43+
* @param description descriptive text that appears in the info box
44+
* @param contextInfo additional information like line number and context
45+
* @param lineNumber used for sorting the entries
46+
*/
47+
GotoSymbolItem(@NotNull PsiElement element, @NotNull final String description, @NotNull final String contextInfo, final int lineNumber) {
3548
super(element);
3649
myDescription = description;
50+
myContext = contextInfo;
51+
myLineNumber = lineNumber;
52+
}
53+
54+
@Nullable
55+
@Override
56+
public String getCustomContainerName() {
57+
return myContext;
3758
}
3859

3960
@Nullable
4061
@Override
4162
public String getCustomName() {
4263
return myDescription;
4364
}
65+
66+
int getLineNumber() {
67+
return myLineNumber;
68+
}
69+
4470
}

src/de/halirutan/mathematica/codeinsight/navigation/MathematicaGotoRelatedProvider.java

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,45 +23,91 @@
2323

2424
import com.intellij.navigation.GotoRelatedItem;
2525
import com.intellij.navigation.GotoRelatedProvider;
26+
import com.intellij.openapi.editor.Document;
27+
import com.intellij.openapi.project.Project;
28+
import com.intellij.openapi.util.TextRange;
29+
import com.intellij.psi.PsiDocumentManager;
2630
import com.intellij.psi.PsiElement;
2731
import com.intellij.psi.PsiReference;
2832
import com.intellij.psi.impl.source.tree.LeafPsiElement;
33+
import com.intellij.util.containers.SortedList;
2934
import de.halirutan.mathematica.parsing.MathematicaElementTypes;
3035
import de.halirutan.mathematica.parsing.psi.api.Symbol;
31-
import de.halirutan.mathematica.parsing.psi.util.GlobalDefinitionCollector;
32-
import de.halirutan.mathematica.parsing.psi.util.GlobalDefinitionCollector.AssignmentProperty;
33-
import de.halirutan.mathematica.parsing.psi.util.LocalizationConstruct.ConstructType;
3436
import org.jetbrains.annotations.NotNull;
3537

36-
import java.util.ArrayList;
37-
import java.util.HashSet;
38+
import java.util.Comparator;
3839
import java.util.List;
39-
import java.util.Map;
4040

4141
/**
42+
* Provides functionality to navigate through different usages of the symbol under the caret.
43+
* It will take the correct scope which means that it won't stupidly highlight symbols with the same name.
44+
* Rather, it will find out if the symbol is globally defined, in a Module, or in any other scoping construct.
45+
* Then, the list of suggestions contains only correct places which really refer to usages of the current symbol.
4246
* @author patrick (28.12.16).
4347
*/
4448
public class MathematicaGotoRelatedProvider extends GotoRelatedProvider {
4549

4650
@NotNull
4751
@Override
4852
public List<? extends GotoRelatedItem> getItems(@NotNull PsiElement psiElement) {
49-
ArrayList<GotoRelatedItem> declarations = new ArrayList<>();
53+
// I want the entries in the suggestion window to be sorted by line number!
54+
SortedList<GotoSymbolItem> declarations = new SortedList<>(Comparator.comparingInt(GotoSymbolItem::getLineNumber));
5055
if (psiElement instanceof LeafPsiElement && ((LeafPsiElement) psiElement).getElementType().equals(MathematicaElementTypes.IDENTIFIER)) {
5156
psiElement = psiElement.getParent();
5257
}
5358
if (psiElement instanceof Symbol) {
59+
final Project project = psiElement.getProject();
60+
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
61+
final Document document = documentManager.getDocument(psiElement.getContainingFile());
62+
if (document == null) {
63+
return declarations;
64+
}
5465
PsiReference ref = psiElement.getReference();
5566
if (ref != null) {
5667
PsiElement resolve = ref.resolve();
5768
if (resolve != null) {
58-
if (resolve instanceof Symbol && ((Symbol) resolve).getLocalizationConstruct().equals(ConstructType.NULL)) {
59-
GlobalDefinitionCollector collector = new GlobalDefinitionCollector(psiElement.getContainingFile());
60-
Map<String, HashSet<AssignmentProperty>> assignments = collector.getAssignments();
61-
for (AssignmentProperty property : assignments.get(((Symbol) resolve).getSymbolName())) {
62-
String text = property.myLhsOfAssignment.getText();
63-
GotoRelatedItem item = new GotoSymbolItem(property.myAssignmentSymbol, text.substring(0, Math.min(text.length(),50)));
64-
declarations.add(item);
69+
if (resolve instanceof Symbol) {
70+
final PsiReference[] resolveReferences = resolve.getReferences();
71+
for (PsiReference reference : resolveReferences) {
72+
final PsiElement usageElement = reference.getElement();
73+
if (usageElement instanceof Symbol && usageElement.isValid()) {
74+
// What follows is that want to collect code around the found element.
75+
// I will collect neighbouring PsiElements but not more than 20 characters to the right and
76+
// to the left of the current usageElement.
77+
final int elementTextOffset = usageElement.getTextOffset();
78+
final int lineNumber = document.getLineNumber(elementTextOffset);
79+
final int lineStartOffset = document.getLineStartOffset(lineNumber);
80+
final int lineEndOffset = document.getLineEndOffset(lineNumber);
81+
assert lineStartOffset <= lineEndOffset;
82+
83+
PsiElement displayStart = usageElement;
84+
PsiElement displayEnd = usageElement;
85+
while (displayStart.getPrevSibling() != null) {
86+
PsiElement tmpStart = displayStart.getPrevSibling();
87+
if (usageElement.getTextOffset() - tmpStart.getTextOffset() > 20
88+
|| tmpStart.getTextOffset() < lineStartOffset) break;
89+
90+
displayStart = tmpStart;
91+
}
92+
93+
while (displayEnd.getNextSibling() != null) {
94+
PsiElement tmpEnd = displayEnd.getNextSibling();
95+
if (tmpEnd.getTextOffset() - (usageElement.getTextOffset() + usageElement.getTextLength()) > 20
96+
|| tmpEnd.getTextOffset() + tmpEnd.getTextLength() > lineEndOffset) break;
97+
98+
displayEnd = tmpEnd;
99+
}
100+
101+
final String lineText = document.getText(
102+
TextRange.create(displayStart.getTextOffset(), displayEnd.getTextOffset() + displayEnd.getTextLength()));
103+
final GotoSymbolItem item = new GotoSymbolItem(
104+
usageElement,
105+
lineText,
106+
"(" + (lineNumber+1) + " in " + ((Symbol) resolve).getLocalizationConstruct() +")", lineNumber);
107+
declarations.add(item);
108+
109+
}
110+
65111
}
66112
}
67113
}

src/de/halirutan/mathematica/parsing/psi/util/LocalizationConstruct.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,42 @@ public static ConstructType getType(String name) {
114114

115115
public enum ConstructType {
116116
MODULE, BLOCK, WITH, FUNCTION, DYNAMICMODULE, TABLE, DO, SUM, NULL, INTEGRATE, NSUM, PLOT, PLOT3D, CONTOURPLOT, CONTOURPLOT3D,
117-
LIMIT, RULEDELAYED, SETDELAYEDPATTERN, MANIPULATE, COMPILE, ANONYMOUSFUNCTION, PARAMETRICPLOT, PARAMETRICPLOT3D
117+
LIMIT, RULEDELAYED, SETDELAYEDPATTERN, MANIPULATE, COMPILE, ANONYMOUSFUNCTION, PARAMETRICPLOT, PARAMETRICPLOT3D;
118+
119+
120+
@Override
121+
public String toString() {
122+
switch (this) {
123+
case ANONYMOUSFUNCTION:
124+
return "Anonymous Function";
125+
case DYNAMICMODULE:
126+
return "DynamicModule";
127+
case NSUM:
128+
return "NSum";
129+
case PLOT3D:
130+
return "Plot3D";
131+
case CONTOURPLOT:
132+
return "ContourPlot";
133+
case CONTOURPLOT3D:
134+
return "ContourPlot3D";
135+
case RULEDELAYED:
136+
return "RuleDelayed";
137+
case SETDELAYEDPATTERN:
138+
return ":= Pattern";
139+
case PARAMETRICPLOT:
140+
return "ParametricPlot";
141+
case PARAMETRICPLOT3D:
142+
return "ParametricPlot3D";
143+
case NULL:
144+
return "file scope";
145+
default:
146+
String str = name().toLowerCase();
147+
str = str.substring(0,1).toUpperCase() + str.substring(1);
148+
return str;
149+
}
150+
151+
152+
}
118153
}
119154

120155

0 commit comments

Comments
 (0)