fix(java): resolve navigation and usages against the text just typed (#2759)

Right after typing in a Java file, Show Usages answered for the wrong symbol and Go to Declaration could do nothing. Usages, Find Usages and hierarchy now wait for the editor's edits to sync before sending the caret position, and the java-usages commands (usages, implementations, hierarchy, configuration) wait for jdtls to reconcile queued document changes before resolving a position (bundle 1.13.0, rebuilt reproducibly from source). File-system events (e.g. the build writing target/classes) now only drop cached navigation answers instead of discarding an in-flight Go to Declaration.
This commit is contained in:
l0ng-ai
2026-11-12 01:33:25 +08:00
committed by GitHub
parent fba1f02375
commit 40aa7e4899
15 changed files with 113 additions and 32 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: OpenIDEA Java usages
Bundle-SymbolicName: ai.openidea.usages;singleton:=true
Bundle-Version: 1.12.0
Bundle-Version: 1.13.0
Bundle-RequiredExecutionEnvironment: JavaSE-21
Require-Bundle: org.eclipse.jdt.ls.core,org.eclipse.jdt.core,
org.eclipse.jdt.core.manipulation,org.eclipse.core.runtime,
+1 -1
View File
@@ -88,7 +88,7 @@ is not a claim of full IntelliJ feature parity.
## Rebuild and delivery
The checked-in jar is embedded by ide-sdk `include_bytes!`, installed as
`java-usages-1.12.0.jar`, and added alongside existing initialization bundles.
`java-usages-1.13.0.jar`, and added alongside existing initialization bundles.
Users need no compiler, Maven or Python. Manifest/install version must change
when replacing the bundle because OSGi caches bundles.
Binary file not shown.
@@ -0,0 +1,21 @@
package ai.openidea;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.ls.core.internal.JobHelpers;
import org.eclipse.jdt.ls.core.internal.handlers.BaseDocumentLifeCycleHandler;
/** What a command that reads an editor's position needs before it resolves the position. */
public final class Documents {
private Documents() {}
/**
* Waits for the queued document changes to be reconciled, as JDT LS's own position requests
* do: `workspace/executeCommand` does not, so a position sent right after an edit would
* be resolved against the element structure from before it.
*/
public static void awaitChanges(IProgressMonitor monitor) {
JobHelpers.waitForJobs(BaseDocumentLifeCycleHandler.DOCUMENT_LIFE_CYCLE_JOBS, monitor);
if (monitor.isCanceled()) throw new OperationCanceledException();
}
}
@@ -1,5 +1,6 @@
package ai.openidea.configuration;
import ai.openidea.Documents;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -96,6 +97,7 @@ public final class ConfigurationCommand implements IDelegateCommandHandler {
@Override
public Object executeCommand(String command, List<Object> args, IProgressMonitor monitor) throws Exception {
if (command.equals("openidea.java.configuration.warmup")) return ConfigurationWarmup.request(args);
Documents.awaitChanges(monitor);
String uri = (String) args.get(0);
String key = args.get(1) instanceof String s ? s : null;
int line = ((Number) args.get(2)).intValue(), column = ((Number) args.get(3)).intValue();
@@ -1,5 +1,6 @@
package ai.openidea.hierarchy;
import ai.openidea.Documents;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
@@ -44,6 +45,7 @@ public final class HierarchyCommand implements IDelegateCommandHandler {
@Override
public Object executeCommand(String command, List<Object> arguments, IProgressMonitor monitor) throws Exception {
Documents.awaitChanges(monitor);
String uri = (String) arguments.get(0);
int line = ((Number) arguments.get(1)).intValue();
int column = ((Number) arguments.get(2)).intValue();
@@ -1,5 +1,6 @@
package ai.openidea.implementations;
import ai.openidea.Documents;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -27,6 +28,7 @@ public final class ImplementationsCommand implements IDelegateCommandHandler {
@Override
public Object executeCommand(String command, List<Object> arguments, IProgressMonitor monitor) throws Exception {
Documents.awaitChanges(monitor);
List<Location> locations = new ArrayList<>();
boolean complete = find(arguments, locations, monitor);
return Map.of("locations", locations, "complete", complete);
@@ -1,5 +1,6 @@
package ai.openidea.usages;
import ai.openidea.Documents;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
@@ -29,6 +30,7 @@ import org.eclipse.lsp4j.*;
public final class UsagesCommand implements IDelegateCommandHandler {
@Override
public Object executeCommand(String command, List<Object> arguments, IProgressMonitor monitor) throws Exception {
Documents.awaitChanges(monitor);
String uri = (String) arguments.get(0);
int line = ((Number) arguments.get(1)).intValue();
int column = ((Number) arguments.get(2)).intValue();