Getting external libraries via jdt.ls extension (#7679)

Signed-off-by: Valeriy Svydenko <vsvydenk@redhat.com>
6.19.x
Valeriy Svydenko 2017-12-07 15:31:28 +02:00 committed by Thomas Mäder
parent 6f8fcf0871
commit 1f5cd7a4e5
24 changed files with 622 additions and 331 deletions

View File

@ -69,6 +69,10 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-ide-app</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.ls.jdt</groupId>
<artifactId>jdt.ls.extension.api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-debugger-ide</artifactId>
@ -77,10 +81,6 @@
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-java-ext-lang-client</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.plugin</groupId>
<artifactId>che-plugin-java-ext-lang-shared</artifactId>
</dependency>
<dependency>
<groupId>org.vectomatic</groupId>
<artifactId>lib-gwt-svg</artifactId>

View File

@ -18,10 +18,12 @@ import org.eclipse.che.api.debug.shared.model.Location;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.editor.EditorAgent;
import org.eclipse.che.ide.api.resources.VirtualFile;
import org.eclipse.che.ide.ext.java.client.navigation.service.JavaNavigationService;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.ext.java.client.service.JavaLanguageExtensionServiceClient;
import org.eclipse.che.ide.ext.java.client.tree.JavaNodeFactory;
import org.eclipse.che.ide.ext.java.client.tree.library.JarFileNode;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.jdt.ls.extension.api.dto.ExternalLibrariesParameters;
import org.eclipse.che.plugin.debugger.ide.debug.FileResourceLocationHandler;
/**
@ -32,24 +34,27 @@ import org.eclipse.che.plugin.debugger.ide.debug.FileResourceLocationHandler;
@Singleton
public class ExternalResourceLocationHandler extends FileResourceLocationHandler {
private final JavaNavigationService javaNavigationService;
private DtoFactory dtoFactory;
private JavaLanguageExtensionServiceClient service;
private final JavaNodeFactory nodeFactory;
@Inject
public ExternalResourceLocationHandler(
EditorAgent editorAgent,
DtoFactory dtoFactory,
AppContext appContext,
JavaNavigationService javaNavigationService,
JavaLanguageExtensionServiceClient service,
JavaNodeFactory nodeFactory) {
super(editorAgent, appContext);
this.dtoFactory = dtoFactory;
this.service = service;
this.javaNavigationService = javaNavigationService;
this.nodeFactory = nodeFactory;
}
@Override
public boolean isSuitedFor(Location location) {
return location.isExternalResource() && location.getExternalResourceId() != 0;
return location.isExternalResource() && location.getExternalResourceId() != null;
}
@Override
@ -73,11 +78,15 @@ public class ExternalResourceLocationHandler extends FileResourceLocationHandler
final Location location, final AsyncCallback<VirtualFile> callback) {
final String className = extractOuterClassFqn(location.getTarget());
final int libId = location.getExternalResourceId();
final String libId = location.getExternalResourceId();
final Path projectPath = new Path(location.getResourceProjectPath());
javaNavigationService
.getEntry(projectPath, libId, className)
ExternalLibrariesParameters params = dtoFactory.createDto(ExternalLibrariesParameters.class);
params.setProjectUri(location.getResourceProjectPath());
params.setNodeId(libId);
params.setNodePath(className);
service
.libraryEntry(params)
.then(
jarEntry -> {
final JarFileNode file =

View File

@ -72,7 +72,7 @@ public class JdbLocation implements Location {
}
@Override
public int getExternalResourceId() {
public String getExternalResourceId() {
return internal.getExternalResourceId();
}

View File

@ -85,14 +85,15 @@ public class JavaDebuggerUtils {
String typeProjectPath = type.getJavaProject().getPath().toOSString();
if (type.isBinary()) {
IClassFile classFile = type.getClassFile();
int libId = classFile.getAncestor(IPackageFragmentRoot.PACKAGE_FRAGMENT_ROOT).hashCode();
String libId =
classFile.getAncestor(IPackageFragmentRoot.PACKAGE_FRAGMENT_ROOT).getHandleIdentifier();
return new LocationImpl(fqn, location.lineNumber(), true, libId, typeProjectPath, null, -1);
} else {
ICompilationUnit compilationUnit = type.getCompilationUnit();
typeProjectPath = type.getJavaProject().getPath().toOSString();
String resourcePath = compilationUnit.getPath().toOSString();
return new LocationImpl(
resourcePath, location.lineNumber(), false, -1, typeProjectPath, null, -1);
resourcePath, location.lineNumber(), false, null, typeProjectPath, null, -1);
}
}

View File

@ -21,10 +21,6 @@ import static org.eclipse.che.ide.part.perspectives.project.ProjectPerspective.P
import com.google.common.base.Optional;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.List;
import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.OperationException;
import org.eclipse.che.api.promises.client.PromiseError;
import org.eclipse.che.ide.api.action.AbstractPerspectiveAction;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.app.AppContext;
@ -35,9 +31,8 @@ import org.eclipse.che.ide.api.resources.Resource;
import org.eclipse.che.ide.ext.java.client.JavaLocalizationConstant;
import org.eclipse.che.ide.ext.java.client.JavaResources;
import org.eclipse.che.ide.ext.java.client.project.classpath.ClasspathResolver;
import org.eclipse.che.ide.ext.java.client.project.classpath.service.ClasspathServiceClient;
import org.eclipse.che.ide.ext.java.client.resource.SourceFolderMarker;
import org.eclipse.che.ide.ext.java.shared.dto.classpath.ClasspathEntryDto;
import org.eclipse.che.ide.ext.java.client.service.JavaLanguageExtensionServiceClient;
/**
* The action which marks a folder into the project as source folder.
@ -47,7 +42,7 @@ import org.eclipse.che.ide.ext.java.shared.dto.classpath.ClasspathEntryDto;
@Singleton
public class MarkDirAsSourceAction extends AbstractPerspectiveAction {
private final AppContext appContext;
private final ClasspathServiceClient classpathService;
private final JavaLanguageExtensionServiceClient extensionService;
private final ClasspathResolver classpathResolver;
private final NotificationManager notificationManager;
@ -55,7 +50,7 @@ public class MarkDirAsSourceAction extends AbstractPerspectiveAction {
public MarkDirAsSourceAction(
JavaResources javaResources,
AppContext appContext,
ClasspathServiceClient classpathService,
JavaLanguageExtensionServiceClient extensionService,
ClasspathResolver classpathResolver,
NotificationManager notificationManager,
JavaLocalizationConstant locale) {
@ -66,7 +61,7 @@ public class MarkDirAsSourceAction extends AbstractPerspectiveAction {
javaResources.sourceFolder());
this.appContext = appContext;
this.classpathService = classpathService;
this.extensionService = extensionService;
this.classpathResolver = classpathResolver;
this.notificationManager = notificationManager;
}
@ -81,24 +76,18 @@ public class MarkDirAsSourceAction extends AbstractPerspectiveAction {
checkState(project.isPresent());
classpathService
.getClasspath(project.get().getLocation().toString())
extensionService
.classpathTree(project.get().getLocation().toString())
.then(
new Operation<List<ClasspathEntryDto>>() {
@Override
public void apply(List<ClasspathEntryDto> arg) throws OperationException {
classpathResolver.resolveClasspathEntries(arg);
classpathResolver.getSources().add(resource.getLocation().toString());
classpathResolver.updateClasspath();
}
classpathEntries -> {
classpathResolver.resolveClasspathEntries(classpathEntries);
classpathResolver.getSources().add(resource.getLocation().toString());
classpathResolver.updateClasspath();
})
.catchError(
new Operation<PromiseError>() {
@Override
public void apply(PromiseError arg) throws OperationException {
notificationManager.notify(
"Can't get classpath", arg.getMessage(), FAIL, EMERGE_MODE);
}
error -> {
notificationManager.notify(
"Can't get classpath", error.getMessage(), FAIL, EMERGE_MODE);
});
}

View File

@ -21,10 +21,6 @@ import static org.eclipse.che.ide.part.perspectives.project.ProjectPerspective.P
import com.google.common.base.Optional;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.List;
import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.OperationException;
import org.eclipse.che.api.promises.client.PromiseError;
import org.eclipse.che.ide.api.action.AbstractPerspectiveAction;
import org.eclipse.che.ide.api.action.ActionEvent;
import org.eclipse.che.ide.api.app.AppContext;
@ -35,9 +31,8 @@ import org.eclipse.che.ide.api.resources.Resource;
import org.eclipse.che.ide.ext.java.client.JavaLocalizationConstant;
import org.eclipse.che.ide.ext.java.client.JavaResources;
import org.eclipse.che.ide.ext.java.client.project.classpath.ClasspathResolver;
import org.eclipse.che.ide.ext.java.client.project.classpath.service.ClasspathServiceClient;
import org.eclipse.che.ide.ext.java.client.resource.SourceFolderMarker;
import org.eclipse.che.ide.ext.java.shared.dto.classpath.ClasspathEntryDto;
import org.eclipse.che.ide.ext.java.client.service.JavaLanguageExtensionServiceClient;
/**
* The action which unmarks a folder into the project as source folder.
@ -47,7 +42,7 @@ import org.eclipse.che.ide.ext.java.shared.dto.classpath.ClasspathEntryDto;
@Singleton
public class UnmarkDirAsSourceAction extends AbstractPerspectiveAction {
private final AppContext appContext;
private final ClasspathServiceClient classpathService;
private final JavaLanguageExtensionServiceClient extensionService;
private final ClasspathResolver classpathResolver;
private final NotificationManager notificationManager;
@ -55,7 +50,7 @@ public class UnmarkDirAsSourceAction extends AbstractPerspectiveAction {
public UnmarkDirAsSourceAction(
JavaResources javaResources,
AppContext appContext,
ClasspathServiceClient classpathService,
JavaLanguageExtensionServiceClient extensionService,
ClasspathResolver classpathResolver,
NotificationManager notificationManager,
JavaLocalizationConstant locale) {
@ -66,7 +61,7 @@ public class UnmarkDirAsSourceAction extends AbstractPerspectiveAction {
javaResources.sourceFolder());
this.appContext = appContext;
this.classpathService = classpathService;
this.extensionService = extensionService;
this.classpathResolver = classpathResolver;
this.notificationManager = notificationManager;
}
@ -81,24 +76,18 @@ public class UnmarkDirAsSourceAction extends AbstractPerspectiveAction {
checkState(project.isPresent());
classpathService
.getClasspath(project.get().getLocation().toString())
extensionService
.classpathTree(project.get().getLocation().toString())
.then(
new Operation<List<ClasspathEntryDto>>() {
@Override
public void apply(List<ClasspathEntryDto> arg) throws OperationException {
classpathResolver.resolveClasspathEntries(arg);
classpathResolver.getSources().remove(resource.getLocation().toString());
classpathResolver.updateClasspath();
}
classpathEntries -> {
classpathResolver.resolveClasspathEntries(classpathEntries);
classpathResolver.getSources().remove(resource.getLocation().toString());
classpathResolver.updateClasspath();
})
.catchError(
new Operation<PromiseError>() {
@Override
public void apply(PromiseError arg) throws OperationException {
notificationManager.notify(
"Can't get classpath", arg.getMessage(), FAIL, EMERGE_MODE);
}
error -> {
notificationManager.notify(
"Can't get classpath", error.getMessage(), FAIL, EMERGE_MODE);
});
}

View File

@ -20,7 +20,7 @@ import java.util.Map;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.promises.client.js.Promises;
import org.eclipse.che.ide.ext.java.client.project.classpath.ClasspathChangedEvent;
import org.eclipse.che.ide.ext.java.client.project.classpath.service.ClasspathServiceClient;
import org.eclipse.che.ide.ext.java.client.service.JavaLanguageExtensionServiceClient;
import org.eclipse.che.ide.ext.java.shared.dto.classpath.ClasspathEntryDto;
/**
@ -32,14 +32,13 @@ import org.eclipse.che.ide.ext.java.shared.dto.classpath.ClasspathEntryDto;
public class ClasspathContainer implements ClasspathChangedEvent.ClasspathChangedHandler {
public static String JRE_CONTAINER = "org.eclipse.jdt.launching.JRE_CONTAINER";
private final ClasspathServiceClient classpathServiceClient;
private final JavaLanguageExtensionServiceClient extensionService;
private Map<String, Promise<List<ClasspathEntryDto>>> classpathes;
@Inject
public ClasspathContainer(ClasspathServiceClient classpathServiceClient, EventBus eventBus) {
this.classpathServiceClient = classpathServiceClient;
public ClasspathContainer(
JavaLanguageExtensionServiceClient extensionService, EventBus eventBus) {
this.extensionService = extensionService;
classpathes = new HashMap<>();
eventBus.addHandler(ClasspathChangedEvent.TYPE, this);
@ -56,7 +55,7 @@ public class ClasspathContainer implements ClasspathChangedEvent.ClasspathChange
if (classpathes.containsKey(projectPath)) {
return classpathes.get(projectPath);
} else {
Promise<List<ClasspathEntryDto>> result = classpathServiceClient.getClasspath(projectPath);
Promise<List<ClasspathEntryDto>> result = extensionService.classpathTree(projectPath);
classpathes.put(projectPath, result);
return result;
}

View File

@ -11,34 +11,34 @@
*/
package org.eclipse.che.ide.ext.java.client.editor;
import static org.eclipse.che.ide.api.editor.text.LinearRange.createWithStart;
import com.google.common.base.Optional;
import com.google.gwt.core.client.Scheduler;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.eclipse.che.api.promises.client.Operation;
import org.eclipse.che.api.promises.client.OperationException;
import org.eclipse.che.ide.DelayedTask;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.editor.EditorAgent;
import org.eclipse.che.ide.api.editor.EditorPartPresenter;
import org.eclipse.che.ide.api.editor.OpenEditorCallbackImpl;
import org.eclipse.che.ide.api.editor.text.LinearRange;
import org.eclipse.che.ide.api.editor.texteditor.TextEditor;
import org.eclipse.che.ide.api.resources.Container;
import org.eclipse.che.ide.api.resources.File;
import org.eclipse.che.ide.api.resources.Project;
import org.eclipse.che.ide.api.resources.Resource;
import org.eclipse.che.ide.api.resources.VirtualFile;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.ext.java.client.navigation.service.JavaNavigationService;
import org.eclipse.che.ide.ext.java.client.resource.SourceFolderMarker;
import org.eclipse.che.ide.ext.java.client.service.JavaLanguageExtensionServiceClient;
import org.eclipse.che.ide.ext.java.client.tree.JavaNodeFactory;
import org.eclipse.che.ide.ext.java.client.tree.library.JarFileNode;
import org.eclipse.che.ide.ext.java.client.util.JavaUtil;
import org.eclipse.che.ide.ext.java.shared.JarEntry;
import org.eclipse.che.ide.ext.java.shared.OpenDeclarationDescriptor;
import org.eclipse.che.ide.ext.java.shared.dto.ClassContent;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.ide.util.loging.Log;
import org.eclipse.che.jdt.ls.extension.api.dto.ExternalLibrariesParameters;
import org.eclipse.che.jdt.ls.extension.api.dto.JarEntry;
/**
* @author Evgen Vidolob
@ -48,18 +48,24 @@ import org.eclipse.che.ide.util.loging.Log;
public class OpenDeclarationFinder {
private final EditorAgent editorAgent;
private DtoFactory dtoFactory;
private final JavaNavigationService navigationService;
private JavaLanguageExtensionServiceClient extensionService;
private final AppContext appContext;
private JavaNodeFactory javaNodeFactory;
@Inject
public OpenDeclarationFinder(
EditorAgent editorAgent,
DtoFactory dtoFactory,
JavaNavigationService navigationService,
JavaLanguageExtensionServiceClient extensionService,
AppContext appContext,
JavaNodeFactory javaNodeFactory) {
this.editorAgent = editorAgent;
this.dtoFactory = dtoFactory;
this.navigationService = navigationService;
this.extensionService = extensionService;
this.appContext = appContext;
this.javaNodeFactory = javaNodeFactory;
}
@ -93,12 +99,9 @@ public class OpenDeclarationFinder {
navigationService
.findDeclaration(project.get().getLocation(), fqn, offset)
.then(
new Operation<OpenDeclarationDescriptor>() {
@Override
public void apply(OpenDeclarationDescriptor result) throws OperationException {
if (result != null) {
handleDescriptor(project.get().getLocation(), result);
}
result -> {
if (result != null) {
handleDescriptor(project.get().getLocation(), result);
}
});
@ -109,12 +112,9 @@ public class OpenDeclarationFinder {
file.getLocation().toString().replace('/', '.'),
offset)
.then(
new Operation<OpenDeclarationDescriptor>() {
@Override
public void apply(OpenDeclarationDescriptor result) throws OperationException {
if (result != null) {
handleDescriptor(((JarFileNode) file).getProject(), result);
}
result -> {
if (result != null) {
handleDescriptor(((JarFileNode) file).getProject(), result);
}
});
}
@ -134,7 +134,7 @@ public class OpenDeclarationFinder {
if (editor instanceof TextEditor) {
((TextEditor) editor)
.getDocument()
.setSelectedRange(LinearRange.createWithStart(offset).andLength(0), true);
.setSelectedRange(createWithStart(offset).andLength(0), true);
editor.activate(); // force set focus to the editor
}
}
@ -146,102 +146,98 @@ public class OpenDeclarationFinder {
final EditorPartPresenter openedEditor =
editorAgent.getOpenedEditor(Path.valueOf(descriptor.getPath()));
if (openedEditor != null) {
editorAgent.openEditor(
openedEditor.getEditorInput().getFile(),
new OpenEditorCallbackImpl() {
@Override
public void onEditorOpened(EditorPartPresenter editor) {
setCursorAndActivateEditor(editor, descriptor.getOffset());
}
@Override
public void onEditorActivated(EditorPartPresenter editor) {
setCursorAndActivateEditor(editor, descriptor.getOffset());
}
});
activateOpenedEditor(descriptor, openedEditor);
return;
}
if (descriptor.isBinary()) {
navigationService
.getEntry(projectPath, descriptor.getLibId(), descriptor.getPath())
.then(
new Operation<JarEntry>() {
@Override
public void apply(final JarEntry entry) throws OperationException {
navigationService
.getContent(projectPath, descriptor.getLibId(), Path.valueOf(entry.getPath()))
.then(
new Operation<ClassContent>() {
@Override
public void apply(ClassContent content) throws OperationException {
final VirtualFile file =
javaNodeFactory.newJarFileNode(
entry, descriptor.getLibId(), projectPath, null);
editorAgent.openEditor(
file,
new OpenEditorCallbackImpl() {
@Override
public void onEditorOpened(final EditorPartPresenter editor) {
Scheduler.get()
.scheduleDeferred(
new Scheduler.ScheduledCommand() {
@Override
public void execute() {
if (editor instanceof TextEditor) {
((TextEditor) editor)
.getDocument()
.setSelectedRange(
LinearRange.createWithStart(
descriptor.getOffset())
.andLength(0),
true);
editor.activate();
}
}
});
}
});
}
});
}
});
getLibraryEntry(projectPath, descriptor);
} else {
appContext
.getWorkspaceRoot()
.getFile(descriptor.getPath())
.then(
new Operation<Optional<File>>() {
@Override
public void apply(Optional<File> file) throws OperationException {
if (file.isPresent()) {
editorAgent.openEditor(
file.get(),
new OpenEditorCallbackImpl() {
@Override
public void onEditorOpened(final EditorPartPresenter editor) {
Scheduler.get()
.scheduleDeferred(
new Scheduler.ScheduledCommand() {
@Override
public void execute() {
if (editor instanceof TextEditor) {
((TextEditor) editor)
.getDocument()
.setSelectedRange(
LinearRange.createWithStart(
descriptor.getOffset())
.andLength(0),
true);
editor.activate();
}
}
});
}
});
}
}
});
openFileFromWorkspace(descriptor);
}
}
private void activateOpenedEditor(
OpenDeclarationDescriptor descriptor, EditorPartPresenter openedEditor) {
editorAgent.openEditor(
openedEditor.getEditorInput().getFile(),
new OpenEditorCallbackImpl() {
@Override
public void onEditorOpened(EditorPartPresenter editor) {
setCursorAndActivateEditor(editor, descriptor.getOffset());
}
@Override
public void onEditorActivated(EditorPartPresenter editor) {
setCursorAndActivateEditor(editor, descriptor.getOffset());
}
});
}
private void openFileFromWorkspace(OpenDeclarationDescriptor descriptor) {
appContext
.getWorkspaceRoot()
.getFile(descriptor.getPath())
.then(
file -> {
if (file.isPresent()) {
openEditor(descriptor, file.get());
}
});
}
private void getLibraryEntry(Path projectPath, OpenDeclarationDescriptor descriptor) {
ExternalLibrariesParameters entryParams =
dtoFactory.createDto(ExternalLibrariesParameters.class);
entryParams.setNodeId(descriptor.getLibId());
entryParams.setNodePath(descriptor.getPath());
entryParams.setProjectUri(projectPath.toString());
extensionService
.libraryEntry(entryParams)
.then(
entry -> {
openBinaryContent(projectPath, descriptor, entry);
});
}
private void openBinaryContent(
Path projectPath, OpenDeclarationDescriptor descriptor, JarEntry entry) {
ExternalLibrariesParameters params = dtoFactory.createDto(ExternalLibrariesParameters.class);
params.setNodeId(descriptor.getLibId());
params.setNodePath(entry.getPath());
params.setProjectUri(projectPath.toString());
extensionService
.libraryNodeContentByPath(params)
.then(
content -> {
final VirtualFile file =
javaNodeFactory.newJarFileNode(entry, descriptor.getLibId(), projectPath, null);
openEditor(descriptor, file);
});
}
private void openEditor(OpenDeclarationDescriptor descriptor, VirtualFile file) {
editorAgent.openEditor(
file,
new OpenEditorCallbackImpl() {
@Override
public void onEditorOpened(final EditorPartPresenter editor) {
OpenDeclarationFinder.this.onEditorOpened(editor, descriptor);
}
});
}
private void onEditorOpened(EditorPartPresenter editor, OpenDeclarationDescriptor descriptor) {
Scheduler.get()
.scheduleDeferred(
() -> {
if (!(editor instanceof TextEditor)) {
return;
}
((TextEditor) editor)
.getDocument()
.setSelectedRange(createWithStart(descriptor.getOffset()).andLength(0), true);
editor.activate();
});
}
}

View File

@ -10,9 +10,17 @@
*/
package org.eclipse.che.ide.ext.java.client.service;
import static org.eclipse.che.api.promises.client.js.JsPromiseError.create;
import static org.eclipse.che.ide.api.jsonrpc.Constants.WS_AGENT_JSON_RPC_ENDPOINT_ID;
import static org.eclipse.che.ide.ext.java.shared.Constants.CLASS_PATH_TREE;
import static org.eclipse.che.ide.ext.java.shared.Constants.EFFECTIVE_POM_REQUEST_TIMEOUT;
import static org.eclipse.che.ide.ext.java.shared.Constants.FILE_STRUCTURE_REQUEST_TIMEOUT;
import static org.eclipse.che.ide.ext.java.shared.Constants.EXTERNAL_LIBRARIES;
import static org.eclipse.che.ide.ext.java.shared.Constants.EXTERNAL_LIBRARIES_CHILDREN;
import static org.eclipse.che.ide.ext.java.shared.Constants.EXTERNAL_LIBRARY_CHILDREN;
import static org.eclipse.che.ide.ext.java.shared.Constants.EXTERNAL_LIBRARY_ENTRY;
import static org.eclipse.che.ide.ext.java.shared.Constants.EXTERNAL_NODE_CONTENT;
import static org.eclipse.che.ide.ext.java.shared.Constants.FILE_STRUCTURE;
import static org.eclipse.che.ide.ext.java.shared.Constants.REQUEST_TIMEOUT;
import com.google.gwt.jsonp.client.TimeoutException;
import com.google.inject.Inject;
@ -20,10 +28,14 @@ import com.google.inject.Singleton;
import java.util.List;
import org.eclipse.che.api.core.jsonrpc.commons.RequestTransmitter;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.promises.client.js.JsPromiseError;
import org.eclipse.che.api.promises.client.js.Promises;
import org.eclipse.che.api.promises.client.js.RejectFunction;
import org.eclipse.che.ide.ext.java.shared.dto.classpath.ClasspathEntryDto;
import org.eclipse.che.jdt.ls.extension.api.dto.ExtendedSymbolInformation;
import org.eclipse.che.jdt.ls.extension.api.dto.ExternalLibrariesParameters;
import org.eclipse.che.jdt.ls.extension.api.dto.FileStructureCommandParameters;
import org.eclipse.che.jdt.ls.extension.api.dto.Jar;
import org.eclipse.che.jdt.ls.extension.api.dto.JarEntry;
import org.eclipse.che.plugin.languageserver.ide.service.ServiceUtil;
@Singleton
@ -42,12 +54,11 @@ public class JavaLanguageExtensionServiceClient {
requestTransmitter
.newRequest()
.endpointId(WS_AGENT_JSON_RPC_ENDPOINT_ID)
.methodName("java/file-structure")
.methodName(FILE_STRUCTURE)
.paramsAsDto(params)
.sendAndReceiveResultAsListOfDto(
ExtendedSymbolInformation.class, FILE_STRUCTURE_REQUEST_TIMEOUT)
.sendAndReceiveResultAsListOfDto(ExtendedSymbolInformation.class, REQUEST_TIMEOUT)
.onSuccess(resolve::apply)
.onTimeout(() -> reject.apply(JsPromiseError.create(new TimeoutException("Timeout"))))
.onTimeout(() -> onTimeout(reject))
.onFailure(error -> reject.apply(ServiceUtil.getPromiseError(error)));
});
}
@ -71,8 +82,134 @@ public class JavaLanguageExtensionServiceClient {
.onTimeout(
() ->
reject.apply(
JsPromiseError.create(
new TimeoutException("Timeout while getting effective pom."))))
create(new TimeoutException("Timeout while getting effective pom."))))
.onFailure(error -> reject.apply(ServiceUtil.getPromiseError(error))));
}
/**
* Gets external libraries of the project.
*
* @param params external libraries parameters {@link ExternalLibrariesParameters}
* @return list of jars
*/
public Promise<List<Jar>> externalLibraries(ExternalLibrariesParameters params) {
return Promises.create(
(resolve, reject) ->
requestTransmitter
.newRequest()
.endpointId(WS_AGENT_JSON_RPC_ENDPOINT_ID)
.methodName(EXTERNAL_LIBRARIES)
.paramsAsDto(params)
.sendAndReceiveResultAsListOfDto(Jar.class, REQUEST_TIMEOUT)
.onSuccess(resolve::apply)
.onTimeout(() -> onTimeout(reject))
.onFailure(error -> reject.apply(ServiceUtil.getPromiseError(error))));
}
/**
* Gets classpath structure.
*
* @param projectPath path to the project
* @return classpath structure
*/
public Promise<List<ClasspathEntryDto>> classpathTree(String projectPath) {
return Promises.create(
(resolve, reject) ->
requestTransmitter
.newRequest()
.endpointId(WS_AGENT_JSON_RPC_ENDPOINT_ID)
.methodName(CLASS_PATH_TREE)
.paramsAsString(projectPath)
.sendAndReceiveResultAsListOfDto(ClasspathEntryDto.class, REQUEST_TIMEOUT)
.onSuccess(resolve::apply)
.onTimeout(() -> onTimeout(reject))
.onFailure(error -> reject.apply(ServiceUtil.getPromiseError(error))));
}
/**
* Gets children of libraries.
*
* @param params external libraries parameters {@link ExternalLibrariesParameters}
* @return list of jars' entries.
*/
public Promise<List<JarEntry>> externalLibrariesChildren(ExternalLibrariesParameters params) {
return Promises.create(
(resolve, reject) ->
requestTransmitter
.newRequest()
.endpointId(WS_AGENT_JSON_RPC_ENDPOINT_ID)
.methodName(EXTERNAL_LIBRARIES_CHILDREN)
.paramsAsDto(params)
.sendAndReceiveResultAsListOfDto(JarEntry.class, REQUEST_TIMEOUT)
.onSuccess(resolve::apply)
.onTimeout(() -> onTimeout(reject))
.onFailure(error -> reject.apply(ServiceUtil.getPromiseError(error))));
}
/**
* Gets children of the library.
*
* @param params external libraries parameters {@link ExternalLibrariesParameters}
* @return list of entries
*/
public Promise<List<JarEntry>> libraryChildren(ExternalLibrariesParameters params) {
return Promises.create(
(resolve, reject) ->
requestTransmitter
.newRequest()
.endpointId(WS_AGENT_JSON_RPC_ENDPOINT_ID)
.methodName(EXTERNAL_LIBRARY_CHILDREN)
.paramsAsDto(params)
.sendAndReceiveResultAsListOfDto(JarEntry.class, REQUEST_TIMEOUT)
.onSuccess(resolve::apply)
.onTimeout(() -> onTimeout(reject))
.onFailure(error -> reject.apply(ServiceUtil.getPromiseError(error))));
}
/**
* Gets entry.
*
* @param params external libraries parameters {@link ExternalLibrariesParameters}
* @return entry {@link JarEntry}
*/
public Promise<JarEntry> libraryEntry(ExternalLibrariesParameters params) {
return Promises.create(
(resolve, reject) ->
requestTransmitter
.newRequest()
.endpointId(WS_AGENT_JSON_RPC_ENDPOINT_ID)
.methodName(EXTERNAL_LIBRARY_ENTRY)
.paramsAsDto(params)
.sendAndReceiveResultAsDto(JarEntry.class, REQUEST_TIMEOUT)
.onSuccess(resolve::apply)
.onTimeout(() -> onTimeout(reject))
.onFailure(error -> reject.apply(ServiceUtil.getPromiseError(error))));
}
/**
* Gets content of the file from the library by file path.
*
* @param params external libraries parameters {@link ExternalLibrariesParameters}
* @return content of the file
*/
public Promise<String> libraryNodeContentByPath(ExternalLibrariesParameters params) {
return Promises.create(
(resolve, reject) ->
requestTransmitter
.newRequest()
.endpointId(WS_AGENT_JSON_RPC_ENDPOINT_ID)
.methodName(EXTERNAL_NODE_CONTENT)
.paramsAsDto(params)
.sendAndReceiveResultAsString(REQUEST_TIMEOUT)
.onSuccess(resolve::apply)
.onTimeout(() -> onTimeout(reject))
.onFailure(error -> reject.apply(ServiceUtil.getPromiseError(error))));
}
private void onTimeout(RejectFunction reject) {
reject.apply(
create(
new TimeoutException(
"Looks like the language server is taking to long to respond, please try again in sometime.")));
}
}

View File

@ -17,11 +17,11 @@ import org.eclipse.che.ide.ext.java.client.tree.library.JarFileNode;
import org.eclipse.che.ide.ext.java.client.tree.library.JarFolderNode;
import org.eclipse.che.ide.ext.java.client.tree.library.JarNode;
import org.eclipse.che.ide.ext.java.client.tree.library.LibrariesNode;
import org.eclipse.che.ide.ext.java.shared.Jar;
import org.eclipse.che.ide.ext.java.shared.JarEntry;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.ide.resources.tree.ResourceNode.NodeFactory;
import org.eclipse.che.ide.ui.smartTree.data.settings.NodeSettings;
import org.eclipse.che.jdt.ls.extension.api.dto.Jar;
import org.eclipse.che.jdt.ls.extension.api.dto.JarEntry;
/** @author Vlad Zhukovskiy */
@Beta
@ -33,7 +33,8 @@ public interface JavaNodeFactory extends NodeFactory {
JarNode newJarNode(Jar jar, Path project, NodeSettings nodeSettings);
JarFolderNode newJarFolderNode(
JarEntry jarEntry, int libId, Path project, NodeSettings nodeSettings);
JarEntry jarEntry, String libId, Path project, NodeSettings nodeSettings);
JarFileNode newJarFileNode(JarEntry jarEntry, int libId, Path project, NodeSettings nodeSettings);
JarFileNode newJarFileNode(
JarEntry jarEntry, String libId, Path project, NodeSettings nodeSettings);
}

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2012-2017 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.ide.ext.java.client.tree.library;
/** Describes entry type of external library node. */
public enum EntryType {
FOLDER,
PACKAGE,
FILE,
CLASS_FILE;
}

View File

@ -25,7 +25,6 @@ import javax.validation.constraints.NotNull;
import org.eclipse.che.api.debug.shared.model.Location;
import org.eclipse.che.api.debug.shared.model.impl.LocationImpl;
import org.eclipse.che.api.promises.client.Function;
import org.eclipse.che.api.promises.client.FunctionException;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.promises.client.js.Promises;
import org.eclipse.che.ide.api.debug.HasLocation;
@ -38,10 +37,9 @@ import org.eclipse.che.ide.api.resources.ResourceChangedEvent.ResourceChangedHan
import org.eclipse.che.ide.api.resources.ResourceDelta;
import org.eclipse.che.ide.api.resources.VirtualFile;
import org.eclipse.che.ide.api.theme.Style;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.ext.java.client.JavaResources;
import org.eclipse.che.ide.ext.java.client.navigation.service.JavaNavigationService;
import org.eclipse.che.ide.ext.java.shared.JarEntry;
import org.eclipse.che.ide.ext.java.shared.dto.ClassContent;
import org.eclipse.che.ide.ext.java.client.service.JavaLanguageExtensionServiceClient;
import org.eclipse.che.ide.project.node.SyntheticNode;
import org.eclipse.che.ide.project.shared.NodesResources;
import org.eclipse.che.ide.resource.Path;
@ -49,6 +47,8 @@ import org.eclipse.che.ide.ui.smartTree.data.HasAction;
import org.eclipse.che.ide.ui.smartTree.data.Node;
import org.eclipse.che.ide.ui.smartTree.data.settings.NodeSettings;
import org.eclipse.che.ide.ui.smartTree.presentation.NodePresentation;
import org.eclipse.che.jdt.ls.extension.api.dto.ExternalLibrariesParameters;
import org.eclipse.che.jdt.ls.extension.api.dto.JarEntry;
/**
* It might be used for any jar content.
@ -59,11 +59,12 @@ import org.eclipse.che.ide.ui.smartTree.presentation.NodePresentation;
public class JarFileNode extends SyntheticNode<JarEntry>
implements VirtualFile, HasAction, FileEventHandler, ResourceChangedHandler, HasLocation {
private final int libId;
private final String libId;
private final Path project;
private final JavaLanguageExtensionServiceClient service;
private final DtoFactory dtoFactory;
private final JavaResources javaResources;
private final NodesResources nodesResources;
private final JavaNavigationService service;
private final EditorAgent editorAgent;
private final EventBus eventBus;
@ -74,20 +75,22 @@ public class JarFileNode extends SyntheticNode<JarEntry>
@Inject
public JarFileNode(
@Assisted JarEntry jarEntry,
@Assisted int libId,
@Assisted String libId,
@Assisted Path project,
@Assisted NodeSettings nodeSettings,
JavaLanguageExtensionServiceClient service,
DtoFactory dtoFactory,
JavaResources javaResources,
NodesResources nodesResources,
JavaNavigationService service,
EditorAgent editorAgent,
EventBus eventBus) {
super(jarEntry, nodeSettings);
this.libId = libId;
this.project = project;
this.service = service;
this.dtoFactory = dtoFactory;
this.javaResources = javaResources;
this.nodesResources = nodesResources;
this.service = service;
this.editorAgent = editorAgent;
this.eventBus = eventBus;
@ -169,29 +172,13 @@ public class JarFileNode extends SyntheticNode<JarEntry>
/** {@inheritDoc} */
@Override
public Promise<String> getContent() {
if (libId != -1) {
return service
.getContent(project, libId, Path.valueOf(getData().getPath()))
.then(
new Function<ClassContent, String>() {
@Override
public String apply(ClassContent result) throws FunctionException {
JarFileNode.this.contentGenerated = result.isGenerated();
return result.getContent();
}
});
} else {
return service
.getContent(project, getData().getPath())
.then(
new Function<ClassContent, String>() {
@Override
public String apply(ClassContent result) throws FunctionException {
JarFileNode.this.contentGenerated = result.isGenerated();
return result.getContent();
}
});
}
ExternalLibrariesParameters params = dtoFactory.createDto(ExternalLibrariesParameters.class);
params.setProjectUri(project.toString());
params.setNodePath(getData().getPath());
params.setNodeId(libId);
return service
.libraryNodeContentByPath(params)
.then((Function<String, String>) result -> result);
}
/** {@inheritDoc} */

View File

@ -12,10 +12,10 @@
package org.eclipse.che.ide.ext.java.client.tree.library;
import static java.util.Collections.singletonList;
import static org.eclipse.che.ide.ext.java.shared.JarEntry.JarEntryType.CLASS_FILE;
import static org.eclipse.che.ide.ext.java.shared.JarEntry.JarEntryType.FILE;
import static org.eclipse.che.ide.ext.java.shared.JarEntry.JarEntryType.FOLDER;
import static org.eclipse.che.ide.ext.java.shared.JarEntry.JarEntryType.PACKAGE;
import static org.eclipse.che.ide.ext.java.client.tree.library.EntryType.CLASS_FILE;
import static org.eclipse.che.ide.ext.java.client.tree.library.EntryType.FILE;
import static org.eclipse.che.ide.ext.java.client.tree.library.EntryType.FOLDER;
import static org.eclipse.che.ide.ext.java.client.tree.library.EntryType.PACKAGE;
import com.google.common.annotations.Beta;
import com.google.inject.Inject;
@ -24,43 +24,47 @@ import java.util.ArrayList;
import java.util.List;
import javax.validation.constraints.NotNull;
import org.eclipse.che.api.promises.client.Function;
import org.eclipse.che.api.promises.client.FunctionException;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.ide.api.theme.Style;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.ext.java.client.JavaResources;
import org.eclipse.che.ide.ext.java.client.navigation.service.JavaNavigationService;
import org.eclipse.che.ide.ext.java.client.service.JavaLanguageExtensionServiceClient;
import org.eclipse.che.ide.ext.java.client.tree.JavaNodeFactory;
import org.eclipse.che.ide.ext.java.shared.JarEntry;
import org.eclipse.che.ide.project.node.SyntheticNode;
import org.eclipse.che.ide.project.shared.NodesResources;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.ide.ui.smartTree.data.Node;
import org.eclipse.che.ide.ui.smartTree.data.settings.NodeSettings;
import org.eclipse.che.ide.ui.smartTree.presentation.NodePresentation;
import org.eclipse.che.jdt.ls.extension.api.dto.ExternalLibrariesParameters;
import org.eclipse.che.jdt.ls.extension.api.dto.JarEntry;
/** @author Vlad Zhukovskiy */
@Beta
public class JarFolderNode extends SyntheticNode<JarEntry> {
private final int libId;
private final String libId;
private final Path project;
private final JavaNavigationService service;
private final JavaResources javaResources;
private final NodesResources nodesResources;
private final JavaNodeFactory nodeFactory;
private DtoFactory dtoFactory;
private final JavaLanguageExtensionServiceClient service;
@Inject
public JarFolderNode(
@Assisted JarEntry jarEntry,
@Assisted int libId,
@Assisted String libId,
@Assisted Path project,
@Assisted NodeSettings nodeSettings,
JavaNavigationService service,
JavaResources javaResources,
DtoFactory dtoFactory,
JavaLanguageExtensionServiceClient service,
NodesResources nodesResources,
JavaNodeFactory nodeFactory) {
super(jarEntry, nodeSettings);
this.libId = libId;
this.project = project;
this.dtoFactory = dtoFactory;
this.service = service;
this.javaResources = javaResources;
this.nodesResources = nodesResources;
@ -75,32 +79,36 @@ public class JarFolderNode extends SyntheticNode<JarEntry> {
@NotNull
@Override
protected Promise<List<Node>> getChildrenImpl() {
ExternalLibrariesParameters params = dtoFactory.createDto(ExternalLibrariesParameters.class);
params.setProjectUri(project.toString());
params.setNodeId(libId);
params.setNodePath(getData().getPath());
return service
.getChildren(project, libId, Path.valueOf(getData().getPath()))
.externalLibrariesChildren(params)
.then(
new Function<List<JarEntry>, List<Node>>() {
@Override
public List<Node> apply(List<JarEntry> entries) throws FunctionException {
List<Node> nodes = new ArrayList<>();
(Function<List<JarEntry>, List<Node>>)
entries -> {
List<Node> nodes = new ArrayList<>();
for (JarEntry entry : entries) {
if (entry.getType() == FOLDER || entry.getType() == PACKAGE) {
nodes.add(nodeFactory.newJarFolderNode(entry, libId, project, getSettings()));
} else if (entry.getType() == FILE || entry.getType() == CLASS_FILE) {
nodes.add(nodeFactory.newJarFileNode(entry, libId, project, getSettings()));
for (JarEntry entry : entries) {
if (FOLDER.name().equals(entry.getEntryType())
|| PACKAGE.name().equals(entry.getEntryType())) {
nodes.add(nodeFactory.newJarFolderNode(entry, libId, project, getSettings()));
} else if (FILE.name().equals(entry.getEntryType())
|| CLASS_FILE.name().equals(entry.getEntryType())) {
nodes.add(nodeFactory.newJarFileNode(entry, libId, project, getSettings()));
}
}
}
return nodes;
}
});
return nodes;
});
}
@Override
public void updatePresentation(@NotNull NodePresentation presentation) {
presentation.setPresentableText(getData().getName());
presentation.setPresentableIcon(
getData().getType() == PACKAGE
PACKAGE.name().equals(getData().getEntryType())
? javaResources.packageItem()
: nodesResources.simpleFolder());
}

View File

@ -11,10 +11,10 @@
*/
package org.eclipse.che.ide.ext.java.client.tree.library;
import static org.eclipse.che.ide.ext.java.shared.JarEntry.JarEntryType.CLASS_FILE;
import static org.eclipse.che.ide.ext.java.shared.JarEntry.JarEntryType.FILE;
import static org.eclipse.che.ide.ext.java.shared.JarEntry.JarEntryType.FOLDER;
import static org.eclipse.che.ide.ext.java.shared.JarEntry.JarEntryType.PACKAGE;
import static org.eclipse.che.ide.ext.java.client.tree.library.EntryType.CLASS_FILE;
import static org.eclipse.che.ide.ext.java.client.tree.library.EntryType.FILE;
import static org.eclipse.che.ide.ext.java.client.tree.library.EntryType.FOLDER;
import static org.eclipse.che.ide.ext.java.client.tree.library.EntryType.PACKAGE;
import com.google.common.annotations.Beta;
import com.google.inject.Inject;
@ -23,18 +23,19 @@ import java.util.ArrayList;
import java.util.List;
import javax.validation.constraints.NotNull;
import org.eclipse.che.api.promises.client.Function;
import org.eclipse.che.api.promises.client.FunctionException;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.ext.java.client.JavaResources;
import org.eclipse.che.ide.ext.java.client.navigation.service.JavaNavigationService;
import org.eclipse.che.ide.ext.java.client.service.JavaLanguageExtensionServiceClient;
import org.eclipse.che.ide.ext.java.client.tree.JavaNodeFactory;
import org.eclipse.che.ide.ext.java.shared.Jar;
import org.eclipse.che.ide.ext.java.shared.JarEntry;
import org.eclipse.che.ide.project.node.SyntheticNode;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.ide.ui.smartTree.data.Node;
import org.eclipse.che.ide.ui.smartTree.data.settings.NodeSettings;
import org.eclipse.che.ide.ui.smartTree.presentation.NodePresentation;
import org.eclipse.che.jdt.ls.extension.api.dto.ExternalLibrariesParameters;
import org.eclipse.che.jdt.ls.extension.api.dto.Jar;
import org.eclipse.che.jdt.ls.extension.api.dto.JarEntry;
/** @author Vlad Zhukovskiy */
@Beta
@ -42,7 +43,8 @@ public class JarNode extends SyntheticNode<Jar> {
private final Path project;
private final JavaResources javaResources;
private final JavaNavigationService service;
private final DtoFactory dtoFactory;
private final JavaLanguageExtensionServiceClient service;
private final JavaNodeFactory nodeFactory;
@Inject
@ -51,11 +53,13 @@ public class JarNode extends SyntheticNode<Jar> {
@Assisted Path project,
@Assisted NodeSettings nodeSettings,
JavaResources javaResources,
JavaNavigationService service,
DtoFactory dtoFactory,
JavaLanguageExtensionServiceClient service,
JavaNodeFactory nodeFactory) {
super(jar, nodeSettings);
this.project = project;
this.javaResources = javaResources;
this.dtoFactory = dtoFactory;
this.service = service;
this.nodeFactory = nodeFactory;
}
@ -63,29 +67,32 @@ public class JarNode extends SyntheticNode<Jar> {
@NotNull
@Override
protected Promise<List<Node>> getChildrenImpl() {
ExternalLibrariesParameters params = dtoFactory.createDto(ExternalLibrariesParameters.class);
params.setProjectUri(project.toString());
params.setNodeId(getData().getId());
return service
.getLibraryChildren(project, getData().getId())
.libraryChildren(params)
.then(
new Function<List<JarEntry>, List<Node>>() {
@Override
public List<Node> apply(List<JarEntry> entries) throws FunctionException {
List<Node> nodes = new ArrayList<>();
(Function<List<JarEntry>, List<Node>>)
entries -> {
List<Node> nodes = new ArrayList<>();
for (JarEntry entry : entries) {
if (entry.getType() == FOLDER || entry.getType() == PACKAGE) {
nodes.add(
nodeFactory.newJarFolderNode(
entry, getData().getId(), project, getSettings()));
} else if (entry.getType() == FILE || entry.getType() == CLASS_FILE) {
nodes.add(
nodeFactory.newJarFileNode(
entry, getData().getId(), project, getSettings()));
for (JarEntry entry : entries) {
if (FOLDER.name().equals(entry.getEntryType())
|| PACKAGE.name().equals(entry.getEntryType())) {
nodes.add(
nodeFactory.newJarFolderNode(
entry, getData().getId(), project, getSettings()));
} else if (FILE.name().equals(entry.getEntryType())
|| CLASS_FILE.name().equals(entry.getEntryType())) {
nodes.add(
nodeFactory.newJarFileNode(
entry, getData().getId(), project, getSettings()));
}
}
}
return nodes;
}
});
return nodes;
});
}
@Override

View File

@ -21,42 +21,46 @@ import com.google.web.bindery.event.shared.EventBus;
import java.util.List;
import javax.validation.constraints.NotNull;
import org.eclipse.che.api.promises.client.Function;
import org.eclipse.che.api.promises.client.FunctionException;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.ide.api.resources.ResourceChangedEvent;
import org.eclipse.che.ide.api.resources.ResourceChangedEvent.ResourceChangedHandler;
import org.eclipse.che.ide.api.resources.ResourceDelta;
import org.eclipse.che.ide.dto.DtoFactory;
import org.eclipse.che.ide.ext.java.client.JavaResources;
import org.eclipse.che.ide.ext.java.client.navigation.service.JavaNavigationService;
import org.eclipse.che.ide.ext.java.client.service.JavaLanguageExtensionServiceClient;
import org.eclipse.che.ide.ext.java.client.tree.JavaNodeFactory;
import org.eclipse.che.ide.ext.java.shared.Jar;
import org.eclipse.che.ide.project.node.SyntheticNode;
import org.eclipse.che.ide.project.node.SyntheticNodeUpdateEvent;
import org.eclipse.che.ide.resource.Path;
import org.eclipse.che.ide.ui.smartTree.data.Node;
import org.eclipse.che.ide.ui.smartTree.data.settings.NodeSettings;
import org.eclipse.che.ide.ui.smartTree.presentation.NodePresentation;
import org.eclipse.che.jdt.ls.extension.api.dto.ExternalLibrariesParameters;
import org.eclipse.che.jdt.ls.extension.api.dto.Jar;
/** @author Vlad Zhukovskiy */
@Beta
public class LibrariesNode extends SyntheticNode<Path> implements ResourceChangedHandler {
private final JavaNavigationService service;
private final JavaNodeFactory nodeFactory;
private DtoFactory dtoFactory;
private final JavaResources javaResources;
private EventBus eventBus;
private final EventBus eventBus;
private final JavaLanguageExtensionServiceClient service;
@Inject
public LibrariesNode(
@Assisted Path project,
@Assisted NodeSettings nodeSettings,
JavaNavigationService service,
JavaLanguageExtensionServiceClient service,
JavaNodeFactory nodeFactory,
DtoFactory dtoFactory,
JavaResources javaResources,
EventBus eventBus) {
super(project, nodeSettings);
this.service = service;
this.nodeFactory = nodeFactory;
this.dtoFactory = dtoFactory;
this.javaResources = javaResources;
this.eventBus = eventBus;
@ -65,22 +69,21 @@ public class LibrariesNode extends SyntheticNode<Path> implements ResourceChange
@Override
protected Promise<List<Node>> getChildrenImpl() {
ExternalLibrariesParameters params = dtoFactory.createDto(ExternalLibrariesParameters.class);
params.setProjectUri(getData().toString());
return service
.getExternalLibraries(getData())
.externalLibraries(params)
.then(
new Function<List<Jar>, List<Node>>() {
@Override
public List<Node> apply(List<Jar> jars) throws FunctionException {
List<Node> nodes = newArrayListWithCapacity(jars.size());
(Function<List<Jar>, List<Node>>)
jars -> {
List<Node> nodes = newArrayListWithCapacity(jars.size());
for (Jar jar : jars) {
nodes.add(nodeFactory.newJarNode(jar, getData(), getSettings()));
}
for (Jar jar : jars) {
nodes.add(nodeFactory.newJarNode(jar, getData(), getSettings()));
}
return nodes;
}
});
return nodes;
});
}
@Override

View File

@ -22,7 +22,7 @@ import com.google.web.bindery.event.shared.EventBus;
import java.util.List;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.ide.ext.java.client.project.classpath.ClasspathChangedEvent;
import org.eclipse.che.ide.ext.java.client.project.classpath.service.ClasspathServiceClient;
import org.eclipse.che.ide.ext.java.client.service.JavaLanguageExtensionServiceClient;
import org.eclipse.che.ide.ext.java.shared.dto.classpath.ClasspathEntryDto;
import org.junit.Before;
import org.junit.Test;
@ -36,7 +36,7 @@ import org.mockito.junit.MockitoJUnitRunner;
public class ClasspathContainerTest {
private static final String PROJECT_PATH = "/project1";
@Mock private ClasspathServiceClient classpathServiceClient;
@Mock private JavaLanguageExtensionServiceClient classpathServiceClient;
@Mock private EventBus eventBus;
@Mock private Promise<List<ClasspathEntryDto>> classpathEntries;
@ -45,7 +45,7 @@ public class ClasspathContainerTest {
@Before
public void setUp() throws Exception {
when(classpathServiceClient.getClasspath(anyString())).thenReturn(classpathEntries);
when(classpathServiceClient.classpathTree(anyString())).thenReturn(classpathEntries);
}
@Test
@ -57,7 +57,7 @@ public class ClasspathContainerTest {
public void classpathShouldBeAdded() throws Exception {
Promise<List<ClasspathEntryDto>> entries = classpathContainer.getClasspathEntries(PROJECT_PATH);
verify(classpathServiceClient).getClasspath(PROJECT_PATH);
verify(classpathServiceClient).classpathTree(PROJECT_PATH);
assertEquals(classpathEntries, entries);
}
@ -69,7 +69,7 @@ public class ClasspathContainerTest {
Promise<List<ClasspathEntryDto>> entries = classpathContainer.getClasspathEntries(PROJECT_PATH);
verify(classpathServiceClient, never()).getClasspath(PROJECT_PATH);
verify(classpathServiceClient, never()).classpathTree(PROJECT_PATH);
assertEquals(classpathEntries, entries);
}
}

View File

@ -612,7 +612,8 @@ public class JavaNavigation {
OpenDeclarationDescriptor dto =
DtoFactory.getInstance().createDto(OpenDeclarationDescriptor.class);
dto.setPath(classFile.getType().getFullyQualifiedName());
dto.setLibId(classFile.getAncestor(IPackageFragmentRoot.PACKAGE_FRAGMENT_ROOT).hashCode());
dto.setLibId(
classFile.getAncestor(IPackageFragmentRoot.PACKAGE_FRAGMENT_ROOT).getHandleIdentifier());
dto.setBinary(true);
if (classFile.getSourceRange() != null) {
if (element instanceof ISourceReference) {

View File

@ -30,9 +30,18 @@ public final class Constants {
public static final String JAVAC = "javac";
// LS requests timeout constants
public static final int FILE_STRUCTURE_REQUEST_TIMEOUT = 10_000;
public static final int REQUEST_TIMEOUT = 10_000;
public static final int EFFECTIVE_POM_REQUEST_TIMEOUT = 30_000;
// JSON RPC methods
public static final String FILE_STRUCTURE = "java/filestructure";
public static final String EXTERNAL_LIBRARIES = "java/externalLibraries";
public static final String EXTERNAL_LIBRARIES_CHILDREN = "java/externalLibrariesChildren";
public static final String EXTERNAL_LIBRARY_CHILDREN = "java/libraryChildren";
public static final String EXTERNAL_LIBRARY_ENTRY = "java/libraryEntry";
public static final String EXTERNAL_NODE_CONTENT = "java/libraryNodeContentByPath";
public static final String CLASS_PATH_TREE = "java/classpathTree";
private Constants() {
throw new UnsupportedOperationException("Unused constructor.");
}

View File

@ -16,9 +16,9 @@ import org.eclipse.che.dto.shared.DTO;
/** @author Evgen Vidolob */
@DTO
public interface OpenDeclarationDescriptor {
int getLibId();
String getLibId();
void setLibId(int libId);
void setLibId(String libId);
int getOffset();

View File

@ -13,15 +13,27 @@ package org.eclipse.che.plugin.java.languageserver;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.eclipse.che.api.languageserver.service.LanguageServiceUtils.prefixURI;
import static org.eclipse.che.ide.ext.java.shared.Constants.CLASS_PATH_TREE;
import static org.eclipse.che.ide.ext.java.shared.Constants.EFFECTIVE_POM_REQUEST_TIMEOUT;
import static org.eclipse.che.ide.ext.java.shared.Constants.FILE_STRUCTURE_REQUEST_TIMEOUT;
import static org.eclipse.che.ide.ext.java.shared.Constants.EXTERNAL_LIBRARIES;
import static org.eclipse.che.ide.ext.java.shared.Constants.EXTERNAL_LIBRARIES_CHILDREN;
import static org.eclipse.che.ide.ext.java.shared.Constants.EXTERNAL_LIBRARY_CHILDREN;
import static org.eclipse.che.ide.ext.java.shared.Constants.EXTERNAL_LIBRARY_ENTRY;
import static org.eclipse.che.ide.ext.java.shared.Constants.EXTERNAL_NODE_CONTENT;
import static org.eclipse.che.ide.ext.java.shared.Constants.FILE_STRUCTURE;
import static org.eclipse.che.jdt.ls.extension.api.Commands.FILE_STRUCTURE_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.FIND_TESTS_FROM_ENTRY_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.FIND_TESTS_FROM_FOLDER_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.FIND_TESTS_FROM_PROJECT_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.FIND_TESTS_IN_FILE_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.FIND_TEST_BY_CURSOR_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.GET_CLASS_PATH_TREE_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.GET_EFFECTIVE_POM_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.GET_EXTERNAL_LIBRARIES_CHILDREN_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.GET_EXTERNAL_LIBRARIES_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.GET_LIBRARY_CHILDREN_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.GET_LIBRARY_ENTRY_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.GET_LIBRARY_NODE_CONTENT_BY_PATH_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.GET_OUTPUT_DIR_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.RESOLVE_CLASSPATH_COMMAND;
import static org.eclipse.che.jdt.ls.extension.api.Commands.TEST_DETECT_COMMAND;
@ -33,6 +45,7 @@ import com.google.gson.reflect.TypeToken;
import com.google.inject.Inject;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@ -44,8 +57,14 @@ import org.eclipse.che.api.core.jsonrpc.commons.JsonRpcException;
import org.eclipse.che.api.core.jsonrpc.commons.RequestHandlerConfigurator;
import org.eclipse.che.api.languageserver.registry.LanguageServerRegistry;
import org.eclipse.che.api.languageserver.service.LanguageServiceUtils;
import org.eclipse.che.dto.server.DtoFactory;
import org.eclipse.che.ide.ext.java.shared.dto.classpath.ClasspathEntryDto;
import org.eclipse.che.jdt.ls.extension.api.dto.ClasspathEntry;
import org.eclipse.che.jdt.ls.extension.api.dto.ExtendedSymbolInformation;
import org.eclipse.che.jdt.ls.extension.api.dto.ExternalLibrariesParameters;
import org.eclipse.che.jdt.ls.extension.api.dto.FileStructureCommandParameters;
import org.eclipse.che.jdt.ls.extension.api.dto.Jar;
import org.eclipse.che.jdt.ls.extension.api.dto.JarEntry;
import org.eclipse.che.jdt.ls.extension.api.dto.TestFindParameters;
import org.eclipse.che.jdt.ls.extension.api.dto.TestPosition;
import org.eclipse.che.jdt.ls.extension.api.dto.TestPositionParameters;
@ -65,6 +84,8 @@ import org.slf4j.LoggerFactory;
* @author Thomas Mäder
*/
public class JavaLanguageServerExtensionService {
private static final int TIMEOUT = 10;
private final Gson gson;
private final LanguageServerRegistry registry;
@ -89,7 +110,7 @@ public class JavaLanguageServerExtensionService {
public void configureMethods() {
requestHandler
.newConfiguration()
.methodName("java/file-structure")
.methodName(FILE_STRUCTURE)
.paramsAsDto(FileStructureCommandParameters.class)
.resultAsListOfDto(ExtendedSymbolInformationDto.class)
.withFunction(this::executeFileStructure);
@ -100,6 +121,48 @@ public class JavaLanguageServerExtensionService {
.paramsAsString()
.resultAsString()
.withFunction(this::getEffectivePom);
requestHandler
.newConfiguration()
.methodName(EXTERNAL_LIBRARIES)
.paramsAsDto(ExternalLibrariesParameters.class)
.resultAsListOfDto(Jar.class)
.withFunction(this::getProjectExternalLibraries);
requestHandler
.newConfiguration()
.methodName(EXTERNAL_LIBRARIES_CHILDREN)
.paramsAsDto(ExternalLibrariesParameters.class)
.resultAsListOfDto(JarEntry.class)
.withFunction(this::getExternalLibrariesChildren);
requestHandler
.newConfiguration()
.methodName(EXTERNAL_LIBRARY_CHILDREN)
.paramsAsDto(ExternalLibrariesParameters.class)
.resultAsListOfDto(JarEntry.class)
.withFunction(this::getLibraryChildren);
requestHandler
.newConfiguration()
.methodName(EXTERNAL_LIBRARY_ENTRY)
.paramsAsDto(ExternalLibrariesParameters.class)
.resultAsDto(JarEntry.class)
.withFunction(this::getLibraryEntry);
requestHandler
.newConfiguration()
.methodName(EXTERNAL_NODE_CONTENT)
.paramsAsDto(ExternalLibrariesParameters.class)
.resultAsString()
.withFunction(this::getLibraryNodeContentByPath);
requestHandler
.newConfiguration()
.methodName(CLASS_PATH_TREE)
.paramsAsString()
.resultAsListOfDto(ClasspathEntryDto.class)
.withFunction(this::getClasspathTree);
}
/**
@ -113,7 +176,7 @@ public class JavaLanguageServerExtensionService {
executeCommand(GET_OUTPUT_DIR_COMMAND, singletonList(projectUri));
Type targetClassType = new TypeToken<String>() {}.getType();
try {
return gson.fromJson(gson.toJson(result.get(10, TimeUnit.SECONDS)), targetClassType);
return gson.fromJson(gson.toJson(result.get(TIMEOUT, TimeUnit.SECONDS)), targetClassType);
} catch (JsonSyntaxException | InterruptedException | ExecutionException | TimeoutException e) {
throw new JsonRpcException(-27000, e.getMessage());
}
@ -135,7 +198,7 @@ public class JavaLanguageServerExtensionService {
Type targetClassType = new TypeToken<ArrayList<TestPosition>>() {}.getType();
try {
List<TestPosition> positions =
gson.fromJson(gson.toJson(result.get(10, TimeUnit.SECONDS)), targetClassType);
gson.fromJson(gson.toJson(result.get(TIMEOUT, TimeUnit.SECONDS)), targetClassType);
return positions.stream().map(TestPositionDto::new).collect(Collectors.toList());
} catch (JsonSyntaxException | InterruptedException | ExecutionException | TimeoutException e) {
throw new JsonRpcException(-27000, e.getMessage());
@ -153,7 +216,7 @@ public class JavaLanguageServerExtensionService {
executeCommand(RESOLVE_CLASSPATH_COMMAND, singletonList(projectUri));
Type targetClassType = new TypeToken<ArrayList<String>>() {}.getType();
try {
return gson.fromJson(gson.toJson(result.get(10, TimeUnit.SECONDS)), targetClassType);
return gson.fromJson(gson.toJson(result.get(TIMEOUT, TimeUnit.SECONDS)), targetClassType);
} catch (JsonSyntaxException | InterruptedException | ExecutionException | TimeoutException e) {
throw new JsonRpcException(-27000, e.getMessage());
}
@ -253,7 +316,7 @@ public class JavaLanguageServerExtensionService {
* @param params command parameters {@link FileStructureCommandParameters}
* @return file structure tree
*/
public List<ExtendedSymbolInformationDto> executeFileStructure(
private List<ExtendedSymbolInformationDto> executeFileStructure(
FileStructureCommandParameters params) {
LOG.info("Requesting files structure for {}", params);
params.setUri(prefixURI(params.getUri()));
@ -262,7 +325,7 @@ public class JavaLanguageServerExtensionService {
Type targetClassType = new TypeToken<ArrayList<ExtendedSymbolInformation>>() {}.getType();
try {
List<ExtendedSymbolInformation> symbols =
gson.fromJson(gson.toJson(result.get(10, TimeUnit.SECONDS)), targetClassType);
gson.fromJson(gson.toJson(result.get(TIMEOUT, TimeUnit.SECONDS)), targetClassType);
return symbols
.stream()
.map(
@ -299,6 +362,43 @@ public class JavaLanguageServerExtensionService {
}
}
private List<Jar> getProjectExternalLibraries(ExternalLibrariesParameters params) {
params.setProjectUri(prefixURI(params.getProjectUri()));
Type type = new TypeToken<ArrayList<Jar>>() {}.getType();
return doGetList(GET_EXTERNAL_LIBRARIES_COMMAND, params, type);
}
private List<JarEntry> getExternalLibrariesChildren(ExternalLibrariesParameters params) {
params.setProjectUri(prefixURI(params.getProjectUri()));
Type type = new TypeToken<ArrayList<JarEntry>>() {}.getType();
return doGetList(GET_EXTERNAL_LIBRARIES_CHILDREN_COMMAND, params, type);
}
private List<JarEntry> getLibraryChildren(ExternalLibrariesParameters params) {
params.setProjectUri(prefixURI(params.getProjectUri()));
Type type = new TypeToken<ArrayList<JarEntry>>() {}.getType();
return doGetList(GET_LIBRARY_CHILDREN_COMMAND, params, type);
}
private List<ClasspathEntryDto> getClasspathTree(String projectPath) {
String projectUri = prefixURI(projectPath);
Type type = new TypeToken<ArrayList<ClasspathEntry>>() {}.getType();
List<ClasspathEntry> entries = doGetList(GET_CLASS_PATH_TREE_COMMAND, projectUri, type);
return convertToClasspathEntryDto(entries);
}
private JarEntry getLibraryEntry(ExternalLibrariesParameters params) {
params.setProjectUri(prefixURI(params.getProjectUri()));
Type type = new TypeToken<JarEntry>() {}.getType();
return doGetOne(GET_LIBRARY_ENTRY_COMMAND, params, type);
}
private String getLibraryNodeContentByPath(ExternalLibrariesParameters params) {
params.setProjectUri(prefixURI(params.getProjectUri()));
Type type = new TypeToken<String>() {}.getType();
return doGetOne(GET_LIBRARY_NODE_CONTENT_BY_PATH_COMMAND, params, type);
}
private List<String> executeFindTestsCommand(
String commandId,
String fileUri,
@ -308,12 +408,23 @@ public class JavaLanguageServerExtensionService {
List<String> classes) {
TestFindParameters parameters =
new TestFindParameters(fileUri, methodAnnotation, projectAnnotation, offset, classes);
CompletableFuture<Object> result = executeCommand(commandId, singletonList(parameters));
Type targetClassType = new TypeToken<ArrayList<String>>() {}.getType();
Type type = new TypeToken<ArrayList<String>>() {}.getType();
return doGetList(commandId, parameters, type);
}
private <T, P> List<T> doGetList(String command, P params, Type type) {
CompletableFuture<Object> result = executeCommand(command, singletonList(params));
try {
return gson.fromJson(
gson.toJson(result.get(FILE_STRUCTURE_REQUEST_TIMEOUT, TimeUnit.SECONDS)),
targetClassType);
return gson.fromJson(gson.toJson(result.get(TIMEOUT, TimeUnit.SECONDS)), type);
} catch (JsonSyntaxException | InterruptedException | ExecutionException | TimeoutException e) {
throw new JsonRpcException(-27000, e.getMessage());
}
}
private <T, P> T doGetOne(String command, P params, Type type) {
CompletableFuture<Object> result = executeCommand(command, singletonList(params));
try {
return gson.fromJson(gson.toJson(result.get(TIMEOUT, TimeUnit.SECONDS)), type);
} catch (JsonSyntaxException | InterruptedException | ExecutionException | TimeoutException e) {
throw new JsonRpcException(-27000, e.getMessage());
}
@ -337,4 +448,25 @@ public class JavaLanguageServerExtensionService {
fixLocation(child);
}
}
private List<ClasspathEntryDto> convertToClasspathEntryDto(
List<ClasspathEntry> classpathEntries) {
List<ClasspathEntryDto> result = new LinkedList<>();
for (ClasspathEntry classpathEntry : classpathEntries) {
ClasspathEntryDto classpathEntryDto =
DtoFactory.newDto(ClasspathEntryDto.class)
.withEntryKind(classpathEntry.getEntryKind())
.withPath(classpathEntry.getPath());
List<ClasspathEntry> children = classpathEntry.getChildren();
if (children != null) {
classpathEntryDto.withExpandedEntries(convertToClasspathEntryDto(children));
}
result.add(classpathEntryDto);
}
return result;
}
}

View File

@ -42,11 +42,11 @@ public class ZendDbgLocationHandler {
public static final Location createVFS(
String target, String resourceProjectPath, int lineNumber) {
return new LocationImpl(target, lineNumber, false, 0, resourceProjectPath, null, -1);
return new LocationImpl(target, lineNumber, false, "", resourceProjectPath, null, -1);
}
public static final Location createDBG(String resourcePath, int lineNumber) {
return new LocationImpl(resourcePath, lineNumber, false, 0, resourcePath, null, -1);
return new LocationImpl(resourcePath, lineNumber, false, null, resourcePath, null, -1);
}
/**
@ -76,7 +76,7 @@ public class ZendDbgLocationHandler {
target,
lineNumber,
false,
0,
null,
resourceProjectPath,
dbgLocation.getMethod(),
dbgLocation.getThreadId());
@ -92,7 +92,7 @@ public class ZendDbgLocationHandler {
"/projects" + vfsLocation.getTarget(),
vfsLocation.getLineNumber(),
false,
0,
"",
vfsLocation.getResourceProjectPath(),
null,
-1);

View File

@ -29,9 +29,9 @@ public interface LocationDto extends Location {
LocationDto withExternalResource(boolean externalResource);
void setExternalResourceId(int externalResourceId);
void setExternalResourceId(String externalResourceId);
LocationDto withExternalResourceId(int externalResourceId);
LocationDto withExternalResourceId(String externalResourceId);
void setResourceProjectPath(String resourceProjectPath);

View File

@ -23,7 +23,7 @@ public interface Location {
boolean isExternalResource();
/** Returns external resource id in case if {@link #isExternalResource()} return true. */
int getExternalResourceId();
String getExternalResourceId();
/** Returns project path, for resource which we are debugging now. */
String getResourceProjectPath();

View File

@ -21,7 +21,7 @@ public class LocationImpl implements Location {
private final String target;
private final int lineNumber;
private final boolean externalResource;
private final int externalResourceId;
private final String externalResourceId;
private final String resourceProjectPath;
private final Method method;
private final long threadId;
@ -30,7 +30,7 @@ public class LocationImpl implements Location {
String target,
int lineNumber,
boolean externalResource,
int externalResourceId,
String externalResourceId,
String resourceProjectPath,
Method method,
long threadId) {
@ -47,17 +47,21 @@ public class LocationImpl implements Location {
String target,
int lineNumber,
boolean externalResource,
int externalResourceId,
String externalResourceId,
String resourceProjectPath) {
this(target, lineNumber, externalResource, externalResourceId, resourceProjectPath, null, -1);
}
public LocationImpl(String target, int lineNumber, String resourceProjectPath) {
this(target, lineNumber, false, 0, resourceProjectPath, null, -1);
this(target, lineNumber, false, null, resourceProjectPath, null, -1);
}
public LocationImpl(String target, int lineNumber) {
this(target, lineNumber, false, 0, null, null, -1);
this(target, lineNumber, false, null, null, null, -1);
}
public LocationImpl(String target) {
this(target, 0, false, null, null, null, -1);
}
@Override
@ -76,7 +80,7 @@ public class LocationImpl implements Location {
}
@Override
public int getExternalResourceId() {
public String getExternalResourceId() {
return externalResourceId;
}
@ -102,7 +106,7 @@ public class LocationImpl implements Location {
LocationImpl location = (LocationImpl) o;
return lineNumber == location.lineNumber
&& externalResource == location.externalResource
&& externalResourceId == location.externalResourceId
&& externalResourceId.equals(location.externalResourceId)
&& threadId == location.threadId
&& equal(target, location.target)
&& equal(resourceProjectPath, location.resourceProjectPath)