Skip to content

Commit 5cb8bdb

Browse files
committed
fix: support StructureView for AbstractFileType + Always opened element
Signed-off-by: azerr <[email protected]>
1 parent 0c90519 commit 5cb8bdb

File tree

5 files changed

+94
-0
lines changed

5 files changed

+94
-0
lines changed

src/main/java/com/redhat/devtools/lsp4ij/client/features/LSPDocumentSymbolFeature.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
import com.intellij.ide.structureView.StructureViewTreeElement;
1414
import com.intellij.openapi.editor.Document;
15+
import com.intellij.openapi.util.TextRange;
16+
import com.intellij.psi.PsiElement;
1517
import com.intellij.psi.PsiFile;
1618
import com.redhat.devtools.lsp4ij.LSPIJUtils;
1719
import com.redhat.devtools.lsp4ij.features.documentSymbol.DocumentSymbolData;
@@ -127,4 +129,10 @@ public boolean canNavigate(@NotNull DocumentSymbol documentSymbol,
127129
var selectionRange = documentSymbol.getSelectionRange();
128130
return selectionRange != null && selectionRange.getStart() != null;
129131
}
132+
133+
public boolean isSame(@NotNull DocumentSymbolData documentSymbolData,
134+
@NotNull PsiElement psiElement) {
135+
TextRange textRange = documentSymbolData.getSelectionTextRange() != null ? documentSymbolData.getSelectionTextRange() : documentSymbolData.getTextRange();
136+
return textRange.equals(psiElement.getTextRange());
137+
}
130138
}

src/main/java/com/redhat/devtools/lsp4ij/features/documentSymbol/DocumentSymbolData.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.jetbrains.annotations.Nullable;
2626

2727
import javax.swing.Icon;
28+
import java.util.Objects;
2829

2930

3031
/**
@@ -39,6 +40,7 @@ public class DocumentSymbolData extends FakePsiElement {
3940
private final DocumentSymbolData parent;
4041
private final @NotNull LanguageServerItem languageServer;
4142
private volatile TextRange textRange = null;
43+
private volatile TextRange selectionTextRange = null;
4244
private DocumentSymbolData[] cachedChildren;
4345

4446
public DocumentSymbolData(@NotNull DocumentSymbol documentSymbol,
@@ -95,6 +97,21 @@ public TextRange getTextRange() {
9597
return textRange;
9698
}
9799

100+
public @Nullable TextRange getSelectionTextRange() {
101+
if (documentSymbol.getSelectionRange() == null) {
102+
return null;
103+
}
104+
if (selectionTextRange == null) {
105+
synchronized (this) {
106+
if (selectionTextRange == null) {
107+
Range range = documentSymbol.getSelectionRange();
108+
Document document = LSPIJUtils.getDocument(psiFile);
109+
this.selectionTextRange = (document != null) ? LSPIJUtils.toTextRange(range, document) : null;
110+
}
111+
}
112+
}
113+
return selectionTextRange;
114+
}
98115
@Override
99116
public void navigate(boolean requestFocus) {
100117
getClientFeatures().getDocumentSymbolFeature().navigate(documentSymbol, psiFile, requestFocus);
@@ -124,6 +141,26 @@ public boolean canNavigate() {
124141
return cachedChildren;
125142
}
126143

144+
@Override
145+
public boolean equals(Object o) {
146+
if (o == null) {
147+
return false;
148+
}
149+
if (getClass() == o.getClass()) {
150+
DocumentSymbolData that = (DocumentSymbolData) o;
151+
return Objects.equals(documentSymbol, that.documentSymbol);
152+
}
153+
if (o instanceof PsiElement psiElement) {
154+
return getClientFeatures().getDocumentSymbolFeature().isSame(this, psiElement);
155+
}
156+
return false;
157+
}
158+
159+
@Override
160+
public int hashCode() {
161+
return Objects.hashCode(documentSymbol);
162+
}
163+
127164
public @NotNull LSPClientFeatures getClientFeatures() {
128165
return languageServer.getClientFeatures();
129166
}

src/main/java/com/redhat/devtools/lsp4ij/features/documentSymbol/LSPDocumentSymbolStructureViewModel.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
import com.intellij.ide.structureView.StructureViewTreeElement;
1616
import com.intellij.ide.structureView.impl.common.PsiTreeElementBase;
1717
import com.intellij.openapi.editor.Editor;
18+
import com.intellij.psi.PsiElement;
1819
import com.intellij.psi.PsiFile;
1920
import com.intellij.util.ArrayUtil;
2021
import com.redhat.devtools.lsp4ij.LSPFileSupport;
2122
import com.redhat.devtools.lsp4ij.client.indexing.ProjectIndexingManager;
23+
import com.redhat.devtools.lsp4ij.features.semanticTokens.viewProvider.LSPSemanticTokenPsiElement;
2224
import com.redhat.devtools.lsp4ij.internal.PsiFileChangedException;
2325
import org.eclipse.lsp4j.DocumentSymbolParams;
2426
import org.eclipse.lsp4j.TextDocumentIdentifier;
@@ -55,6 +57,12 @@ public boolean isAlwaysLeaf(StructureViewTreeElement element) {
5557
return element.getChildren().length == 0;
5658
}
5759

60+
@Override
61+
protected Class @NotNull [] getSuitableClasses() {
62+
// Any PSI element
63+
return new Class[] {PsiElement.class};
64+
}
65+
5866
@Override
5967
public void dispose() {
6068
super.dispose();
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.redhat.devtools.lsp4ij.features.documentSymbol;
2+
3+
import com.intellij.ide.structureView.StructureViewBuilder;
4+
import com.intellij.ide.structureView.StructureViewBuilderProvider;
5+
import com.intellij.ide.structureView.logical.PhysicalAndLogicalStructureViewBuilder;
6+
import com.intellij.lang.LanguageStructureViewBuilder;
7+
import com.intellij.lang.PsiStructureViewFactory;
8+
import com.intellij.openapi.fileTypes.FileType;
9+
import com.intellij.openapi.fileTypes.impl.AbstractFileType;
10+
import com.intellij.openapi.project.Project;
11+
import com.intellij.openapi.vfs.VirtualFile;
12+
import com.intellij.psi.PsiFile;
13+
import com.intellij.psi.PsiManager;
14+
import com.redhat.devtools.lsp4ij.LanguageServersRegistry;
15+
import com.redhat.devtools.lsp4ij.client.ExecuteLSPFeatureStatus;
16+
import org.jetbrains.annotations.NotNull;
17+
import org.jetbrains.annotations.Nullable;
18+
19+
public class LSPStructureViewBuilderProvider implements StructureViewBuilderProvider {
20+
@Override
21+
public @Nullable StructureViewBuilder getStructureViewBuilder(@NotNull FileType fileType, @NotNull VirtualFile file, @NotNull Project project) {
22+
if (!(fileType instanceof AbstractFileType)) {
23+
return null;
24+
}
25+
if (!LanguageServersRegistry.getInstance().isFileSupported(file, project)) {
26+
// The file is not associated to a language server, don't execute the LSP feature.
27+
return null;
28+
}
29+
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
30+
if (psiFile == null) return null;
31+
32+
PsiStructureViewFactory factory = LanguageStructureViewBuilder.getInstance().forLanguage(psiFile.getLanguage());
33+
if (factory == null) return null;
34+
StructureViewBuilder physicalBuilder = factory.getStructureViewBuilder(psiFile);
35+
return PhysicalAndLogicalStructureViewBuilder.Companion.wrapPhysicalBuilderIfPossible(physicalBuilder, psiFile);
36+
}
37+
}

src/main/resources/META-INF/plugin.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,10 @@
437437
implementationClass="com.redhat.devtools.lsp4ij.features.documentLink.LSPDocumentLinkDocumentationProvider"/>
438438

439439
<!-- LSP textDocument/documentSymbol request support -->
440+
<structureViewBuilder
441+
id="LSPStructureViewBuilderProvider"
442+
factoryClass="com.redhat.devtools.lsp4ij.features.documentSymbol.LSPStructureViewBuilderProvider"
443+
order="last"/>
440444
<lang.psiStructureViewFactory
441445
id="LSPDocumentSymbolStructureViewFactoryForText"
442446
language="TEXT"

0 commit comments

Comments
 (0)