Skip to content

Commit

Permalink
documentSymbols to work for Java files that are not resources (#2823)
Browse files Browse the repository at this point in the history
The makes that the documentSymbols (and probably some other requests)
capable of processing files that are not imported in any way in the
workspace.
It consists of mainly
* Adding capability to create an ICompilationUnit for those files
* Adding extra-logic to resolve an URI for ICompilationUnit that are not
backed by an IFile.

Fixes #2809
  • Loading branch information
mickaelistria authored Sep 26, 2023
1 parent 96b90cb commit 2f3f584
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*******************************************************************************/
package org.eclipse.jdt.ls.core.internal;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

Expand All @@ -23,12 +24,14 @@
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourceAttributes;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.BufferChangedEvent;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.IBufferChangedListener;
import org.eclipse.jdt.core.IOpenable;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
Expand Down Expand Up @@ -84,8 +87,13 @@ public void setContents(String contents) {}

private Object lock = new Object();

private IOpenable fOwner;
private IFile fFile;
private final IOpenable fOwner;
private final IFile fFile;
/**
* The file Path: in case of a resource, the resource workspace-relative
* full path; in case of a plain file, the filesystem location.
*/
public final IPath filePath;
private boolean fIsClosed;

private List<IBufferChangedListener> fBufferListeners;
Expand All @@ -97,13 +105,32 @@ public void setContents(String contents) {}
public DocumentAdapter(IOpenable owner, IFile file) {
fOwner = owner;
fFile = file;
filePath = file.getFullPath();
fBufferListeners = new ArrayList<>(3);
fIsClosed = false;

ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
try {
manager.connect(file.getFullPath(), LocationKind.IFILE, null);
fTextFileBuffer= manager.getTextFileBuffer(file.getFullPath(), LocationKind.IFILE);
manager.connect(filePath, LocationKind.IFILE, null);
fTextFileBuffer= manager.getTextFileBuffer(filePath, LocationKind.IFILE);
} catch (CoreException e) {
}
}

public DocumentAdapter(IOpenable owner, Path path) {
fOwner = owner;
fFile = null;
filePath = IPath.fromPath(path);
fBufferListeners = new ArrayList<>(3);
fIsClosed = false;

ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
try {
manager.connect(filePath, LocationKind.LOCATION, null);
fTextFileBuffer= manager.getTextFileBuffer(filePath, LocationKind.LOCATION);
if (fTextFileBuffer != null) {
fDocument = fTextFileBuffer.getDocument();
}
} catch (CoreException e) {
}
}
Expand Down Expand Up @@ -154,10 +181,10 @@ public void close() {
fDocument.removeDocumentListener(this);
}

if (fTextFileBuffer != null && fFile != null) {
if (fTextFileBuffer != null) {
try {
ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
manager.disconnect(fFile.getFullPath(), LocationKind.NORMALIZE, null);
manager.disconnect(filePath, fFile != null ? LocationKind.NORMALIZE : LocationKind.LOCATION, null);
} catch (CoreException x) {
// ignore
}
Expand Down Expand Up @@ -229,7 +256,9 @@ public boolean isReadOnly() {
if (fTextFileBuffer != null) {
return fTextFileBuffer.isCommitable();
}

if (fFile == null) {
return filePath.toFile().canWrite();
}
ResourceAttributes attributes = fFile.getResourceAttributes();
return attributes != null ? attributes.isReadOnly() : false;
}
Expand Down Expand Up @@ -272,7 +301,7 @@ public void setContents(String contents) {
fDocument = fTextFileBuffer.getDocument();
} else {
ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
fDocument = manager.createEmptyDocument(fFile.getFullPath(), LocationKind.IFILE);
fDocument = manager.createEmptyDocument(filePath, fFile != null ? LocationKind.IFILE : LocationKind.LOCATION);
}
fDocument.addDocumentListener(this);
((ISynchronizable)fDocument).setLockObject(lock);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,21 @@ static ICompilationUnit getFakeCompilationUnit(URI uri, IProgressMonitor monitor

IProject project = JavaLanguageServerPlugin.getProjectsManager().getDefaultProject();
if (project == null || !project.isAccessible()) {
return null;
String fileName = path.getFileName().toString();
if (fileName.endsWith(".java") || fileName.endsWith(".class")) {
fileName = fileName.substring(0, fileName.lastIndexOf('.'));
}
WorkingCopyOwner owner = new WorkingCopyOwner() {
@Override
public IBuffer createBuffer(ICompilationUnit workingCopy) {
return new DocumentAdapter(workingCopy, path);
}
};
try {
return owner.newWorkingCopy(fileName, new IClasspathEntry[] { JavaRuntime.getDefaultJREContainerEntry() }, monitor);
} catch (JavaModelException e) {
return null;
}
}
IJavaProject javaProject = JavaCore.create(project);

Expand Down Expand Up @@ -971,7 +985,20 @@ public static String getFileURI(ICompilationUnit cu) {
* @return
*/
public static String toURI(ICompilationUnit cu) {
return getFileURI(cu.getResource());
if (cu.getResource() != null) {
String uri = getFileURI(cu.getResource());
if (uri != null) {
return uri;
}
}
try {
if (cu.getBuffer() instanceof DocumentAdapter adapter) {
return adapter.filePath.toFile().toURI().toString();
}
} catch (JavaModelException ex) {
JavaLanguageServerPlugin.logException(ex);
}
return null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -33,6 +35,7 @@
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ls.core.internal.ClassFileUtil;
import org.eclipse.jdt.ls.core.internal.WorkspaceHelper;
Expand Down Expand Up @@ -254,6 +257,10 @@ public void testDecompiledSource() throws Exception {
private List<? extends DocumentSymbol> internalGetHierarchicalSymbols(IProject project, IProgressMonitor monitor, String className)
throws JavaModelException, UnsupportedEncodingException, InterruptedException, ExecutionException {
String uri = ClassFileUtil.getURI(project, className);
return getHierarchicalDocumentSymbols(uri, monitor);
}

private List<? extends DocumentSymbol> getHierarchicalDocumentSymbols(String uri, IProgressMonitor monitor) {
TextDocumentIdentifier identifier = new TextDocumentIdentifier(uri);
DocumentSymbolParams params = new DocumentSymbolParams();
params.setTextDocument(identifier);
Expand Down Expand Up @@ -357,5 +364,28 @@ private boolean isValid(Position position) {
return position != null && position.getLine() >= 0 && position.getCharacter() >= 0;
}

@Test
public void testDocumentSymbolsOnPlainFile() throws Exception {
String previous = System.getProperty("GENERATES_METADATA_FILES_AT_PROJECT_ROOT");
File f = File.createTempFile("testDocumentSymbolsOnPlainFile", ".java");
Files.writeString(f.toPath(), """
public class SomeClass {
int someField;
}
""");
try {
cleanUp(); // reset LS so the GENERATES_METADATA_FILES_AT_PROJECT_ROOT takes effect
List<? extends DocumentSymbol> symbols = getHierarchicalDocumentSymbols(f.toURI().toString(), new NullProgressMonitor());
DocumentSymbol classSymbol = symbols.get(0);
assertEquals("someField", classSymbol.getChildren().get(0).getName());
} finally {
f.delete();
if (previous == null) {
System.clearProperty("GENERATES_METADATA_FILES_AT_PROJECT_ROOT");
} else {
System.setProperty("GENERATES_METADATA_FILES_AT_PROJECT_ROOT", previous);
}
}
}

}

0 comments on commit 2f3f584

Please sign in to comment.