Attempt to fix Java LS semantic tokens coming from Boot LS
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
package org.springframework.ide.vscode.boot.java;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -24,7 +23,6 @@ import org.eclipse.lsp4j.SemanticTokensLegend;
|
||||
import org.eclipse.lsp4j.SemanticTokensWithRegistrationOptions;
|
||||
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.CompositeASTVisitor;
|
||||
import org.springframework.ide.vscode.boot.java.semantictokens.JavaSemanticTokensProvider;
|
||||
import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
@@ -41,20 +39,10 @@ public class JdtSemanticTokensHandler implements SemanticTokensHandler {
|
||||
private final Collection<JdtSemanticTokensProvider> tokenProviders;
|
||||
private final SemanticTokensLegend legend;
|
||||
|
||||
private JavaSemanticTokensProvider jdtLsProvider;
|
||||
|
||||
public JdtSemanticTokensHandler(CompilationUnitCache cuCache, JavaProjectFinder projectFinder, Collection<JdtSemanticTokensProvider> tokenProviders) {
|
||||
this.cuCache = cuCache;
|
||||
this.projectFinder = projectFinder;
|
||||
ArrayList<JdtSemanticTokensProvider> tokenProvidersList = new ArrayList<>(tokenProviders.size());
|
||||
for (JdtSemanticTokensProvider tp : tokenProviders) {
|
||||
if (tp instanceof JavaSemanticTokensProvider jdtLsProvider) {
|
||||
this.jdtLsProvider = jdtLsProvider;
|
||||
} else {
|
||||
tokenProvidersList.add(tp);
|
||||
}
|
||||
}
|
||||
this.tokenProviders = tokenProvidersList;
|
||||
this.tokenProviders = tokenProviders;
|
||||
this.legend = new SemanticTokensLegend(
|
||||
tokenProviders.stream().flatMap(tp -> tp.getTokenTypes().stream()).distinct().collect(Collectors.toList()),
|
||||
tokenProviders.stream().flatMap(tp -> tp.getTokenModifiers().stream()).distinct().collect(Collectors.toList())
|
||||
@@ -73,8 +61,6 @@ public class JdtSemanticTokensHandler implements SemanticTokensHandler {
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<SemanticTokenData> semanticTokensFull(TextDocument doc, CancelChecker cancelChecker) {
|
||||
return semanticTokens(doc, cancelChecker, null);
|
||||
@@ -91,19 +77,19 @@ public class JdtSemanticTokensHandler implements SemanticTokensHandler {
|
||||
IJavaProject jp = optProject.get();
|
||||
List<JdtSemanticTokensProvider> applicableTokenProviders = tokenProviders.stream().filter(tp -> tp.isApplicable(jp)).collect(Collectors.toList());
|
||||
if (!applicableTokenProviders.isEmpty()) {
|
||||
return cuCache.withCompilationUnit(jp, URI.create(doc.getUri()), cu -> computeTokens(applicableTokenProviders, jp, cu, r));
|
||||
return cuCache.withCompilationUnit(jp, URI.create(doc.getUri()), cu -> computeTokens(applicableTokenProviders, jp, cu, r, doc));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<SemanticTokenData> computeTokens(List<JdtSemanticTokensProvider> applicableTokenProviders, IJavaProject jp, CompilationUnit cu, Range r) {
|
||||
private List<SemanticTokenData> computeTokens(List<JdtSemanticTokensProvider> applicableTokenProviders, IJavaProject jp, CompilationUnit cu, Range r, TextDocument doc) {
|
||||
if (cu == null) {
|
||||
return null;
|
||||
}
|
||||
Collector<SemanticTokenData> collector = new Collector<>();
|
||||
CompositeASTVisitor visitor = new CompositeASTVisitor();
|
||||
applicableTokenProviders.forEach(tp -> visitor.add(tp.getTokensComputer(jp, cu, collector)));
|
||||
applicableTokenProviders.forEach(tp -> visitor.add(tp.getTokensComputer(jp, doc, cu, collector)));
|
||||
if (r != null) {
|
||||
if (r.getStart() != null) {
|
||||
visitor.setStartOffset(cu.getPosition(r.getStart().getLine(), r.getStart().getCharacter()));
|
||||
@@ -113,10 +99,6 @@ public class JdtSemanticTokensHandler implements SemanticTokensHandler {
|
||||
}
|
||||
}
|
||||
cu.accept(visitor);
|
||||
if (!collector.isEmpty() && jdtLsProvider != null) {
|
||||
// If there are tokens computed then also run JDT LS tokens provider not to lose JDT LS semantic highlights
|
||||
cu.accept(jdtLsProvider.getTokensComputer(jp, cu, collector));
|
||||
}
|
||||
return collector.isEmpty() ? null : collector.get();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,12 +18,13 @@ import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData;
|
||||
import org.springframework.ide.vscode.commons.util.Collector;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
public interface JdtSemanticTokensProvider {
|
||||
|
||||
List<String> getTokenTypes();
|
||||
default List<String> getTokenModifiers() { return Collections.emptyList(); }
|
||||
boolean isApplicable(IJavaProject project);
|
||||
ASTVisitor getTokensComputer(IJavaProject project, CompilationUnit cu, Collector<SemanticTokenData> collector);
|
||||
ASTVisitor getTokensComputer(IJavaProject project, TextDocument doc, CompilationUnit cu, Collector<SemanticTokenData> collector);
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
|
||||
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData;
|
||||
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokensDataProvider;
|
||||
import org.springframework.ide.vscode.commons.util.Collector;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
public class JdtDataQuerySemanticTokensProvider implements JdtSemanticTokensProvider {
|
||||
|
||||
@@ -61,7 +62,7 @@ public class JdtDataQuerySemanticTokensProvider implements JdtSemanticTokensProv
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTVisitor getTokensComputer(IJavaProject jp, CompilationUnit cu, Collector<SemanticTokenData> tokensData) {
|
||||
public ASTVisitor getTokensComputer(IJavaProject jp, TextDocument doc, CompilationUnit cu, Collector<SemanticTokenData> tokensData) {
|
||||
SemanticTokensDataProvider provider = SpringProjectUtil.hasDependencyStartingWith(jp, "hibernate-core", null) ? hqlProvider : jpqlProvider;
|
||||
return new ASTVisitor() {
|
||||
@Override
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.springframework.ide.vscode.boot.java.JdtSemanticTokensProvider;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData;
|
||||
import org.springframework.ide.vscode.commons.util.Collector;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
public class JavaSemanticTokensProvider implements JdtSemanticTokensProvider {
|
||||
|
||||
@@ -39,9 +40,9 @@ public class JavaSemanticTokensProvider implements JdtSemanticTokensProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTVisitor getTokensComputer(IJavaProject project, CompilationUnit cu,
|
||||
public ASTVisitor getTokensComputer(IJavaProject project, TextDocument doc, CompilationUnit cu,
|
||||
Collector<SemanticTokenData> collector) {
|
||||
return new SemanticTokensVisitor(cu, collector);
|
||||
return new SemanticTokensVisitor(project, doc, cu, collector);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,10 +17,7 @@ package org.springframework.ide.vscode.boot.java.semantictokens;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.eclipse.jdt.core.ITypeRoot;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.eclipse.jdt.core.JavaModelException;
|
||||
import org.eclipse.jdt.core.ToolFactory;
|
||||
import org.eclipse.jdt.core.compiler.IScanner;
|
||||
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
|
||||
@@ -57,18 +54,20 @@ import org.eclipse.jdt.core.dom.Type;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.eclipse.jdt.core.dom.TypeLiteral;
|
||||
import org.eclipse.jdt.internal.core.dom.util.DOMASTUtil;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.semantic.tokens.SemanticTokenData;
|
||||
import org.springframework.ide.vscode.commons.util.Collector;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
public class SemanticTokensVisitor extends ASTVisitor {
|
||||
private CompilationUnit cu;
|
||||
private final IScanner scanner;
|
||||
private Collector<SemanticTokenData> collector;
|
||||
|
||||
public SemanticTokensVisitor(CompilationUnit cu, Collector<SemanticTokenData> collector) {
|
||||
public SemanticTokensVisitor(IJavaProject project, TextDocument doc, CompilationUnit cu, Collector<SemanticTokenData> collector) {
|
||||
super(true);
|
||||
this.cu = cu;
|
||||
this.scanner = createScanner(cu);
|
||||
this.scanner = createScanner(project, doc, cu);
|
||||
this.collector = collector;
|
||||
}
|
||||
|
||||
@@ -421,7 +420,11 @@ public class SemanticTokensVisitor extends ASTVisitor {
|
||||
break; // "class" or "interface" keyword tokens
|
||||
case ITerminalSymbols.TokenNameextends:
|
||||
addToken(tokenOffset, tokenLength, TokenType.MODIFIER, 0);
|
||||
acceptNode(node.getSuperclassType());
|
||||
if (node.isInterface()) {
|
||||
acceptNodeList(node.superInterfaceTypes());
|
||||
} else {
|
||||
acceptNode(node.getSuperclassType());
|
||||
}
|
||||
break; // "extends" keyword token
|
||||
case ITerminalSymbols.TokenNameimplements:
|
||||
addToken(tokenOffset, tokenLength, TokenType.MODIFIER, 0);
|
||||
@@ -443,32 +446,27 @@ public class SemanticTokensVisitor extends ASTVisitor {
|
||||
|
||||
/**
|
||||
* Tries to create an {@link IScanner} for the source of the given compilation unit.
|
||||
* @param doc
|
||||
* @param javaProject
|
||||
*
|
||||
* @param cu the compilation unit
|
||||
* @return the scanner, or {@code null} if not available
|
||||
*/
|
||||
private IScanner createScanner(CompilationUnit cu) {
|
||||
final ITypeRoot typeRoot = cu.getTypeRoot();
|
||||
if (typeRoot == null) {
|
||||
private IScanner createScanner(IJavaProject javaProject, TextDocument doc, CompilationUnit cu) {
|
||||
if (doc == null) {
|
||||
return null;
|
||||
}
|
||||
final IJavaProject javaProject = typeRoot.getJavaProject();
|
||||
if (javaProject == null) {
|
||||
return null;
|
||||
}
|
||||
final String source;
|
||||
try {
|
||||
source = typeRoot.getSource();
|
||||
} catch (JavaModelException e) {
|
||||
return null;
|
||||
}
|
||||
final String source = doc.get();
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String sourceLevel = javaProject.getOption(JavaCore.COMPILER_SOURCE, true);
|
||||
final String complianceLevel = javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);
|
||||
final boolean enablePreview = JavaCore.ENABLED.equals(javaProject.getOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, true));
|
||||
final String sourceLevel = JavaCore.VERSION_21;/*javaProject.getOption(JavaCore.COMPILER_SOURCE, true);*/
|
||||
final String complianceLevel = JavaCore.VERSION_21; /*javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true);*/
|
||||
final boolean enablePreview = false; /*JavaCore.ENABLED.equals(javaProject.getOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, true));*/
|
||||
|
||||
final IScanner scanner = ToolFactory.createScanner(false, false, false, sourceLevel, complianceLevel, enablePreview);
|
||||
scanner.setSource(source.toCharArray());
|
||||
|
||||
@@ -50,7 +50,7 @@ public class JdtDataQuerySemanticTokensProviderTest {
|
||||
private List<SemanticTokenData> computeTokens(CompilationUnit cu) {
|
||||
Collector<SemanticTokenData> collector = new Collector<>();
|
||||
CompositeASTVisitor visitor = new CompositeASTVisitor();
|
||||
visitor.add(provider.getTokensComputer(jp, cu, collector));
|
||||
visitor.add(provider.getTokensComputer(jp, null, cu, collector));
|
||||
cu.accept(visitor);
|
||||
return collector.get();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user