This repository has been archived by the owner on Apr 21, 2023. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[LS] support multiple workspace root folders
Fixes #1238
- Loading branch information
1 parent
c059268
commit 52d115d
Showing
11 changed files
with
518 additions
and
8 deletions.
There are no files selected for viewing
123 changes: 123 additions & 0 deletions
123
...eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/WorkspaceFoldersTest.xtend
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2020 TypeFox GmbH (http://www.typefox.io) and others. | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*******************************************************************************/ | ||
package org.eclipse.xtext.ide.tests.server | ||
|
||
import com.google.inject.AbstractModule | ||
import com.google.inject.Inject | ||
import com.google.inject.Module | ||
import com.google.inject.Scopes | ||
import java.io.File | ||
import java.io.FileWriter | ||
import java.util.concurrent.CompletableFuture | ||
import org.eclipse.lsp4j.DidChangeWorkspaceFoldersParams | ||
import org.eclipse.lsp4j.WorkspaceFolder | ||
import org.eclipse.lsp4j.WorkspaceFoldersChangeEvent | ||
import org.eclipse.xtext.ide.server.UriExtensions | ||
import org.eclipse.xtext.ide.server.WorkspaceManager | ||
import org.eclipse.xtext.util.Files | ||
import org.eclipse.xtext.util.Modules2 | ||
import org.junit.Test | ||
|
||
import static org.junit.Assert.assertEquals | ||
|
||
/** | ||
* @author Jan Koehnlein - Initial contribution and API | ||
*/ | ||
class WorkspaceFoldersTest extends AbstractTestLangLanguageServerTest { | ||
|
||
@Inject extension UriExtensions | ||
|
||
@Inject WorkspaceManager workspaceManager | ||
|
||
@Test | ||
def void testInitialize() { | ||
val rootFolder1 = getRoot('root1') | ||
val rootFolder2 = getRoot('root2') | ||
writeFile(rootFolder1, "one.testlang", ''' | ||
type Foo { | ||
Bar bar | ||
} | ||
''') | ||
val twoUri = writeFile(rootFolder2, "two.testlang", ''' | ||
type Bar { | ||
Foo foo | ||
} | ||
''') | ||
initialize[ | ||
workspaceFolders = #[ | ||
new WorkspaceFolder(rootFolder1.toURI.toUriString, 'root1'), | ||
new WorkspaceFolder(rootFolder2.toURI.toUriString, 'root2') | ||
] | ||
] | ||
assertEquals(2, diagnostics.size) | ||
assertEquals(1, diagnostics.get(twoUri).size) | ||
withBuild [ | ||
languageServer.didChangeWorkspaceFolders(new DidChangeWorkspaceFoldersParams => [ | ||
event = new WorkspaceFoldersChangeEvent => [ | ||
removed = #[ | ||
new WorkspaceFolder(rootFolder2.toURI.toUriString, 'root2') | ||
] | ||
] | ||
]) | ||
] | ||
assertEquals(0, diagnostics.get(twoUri).size) | ||
withBuild [ | ||
languageServer.didChangeWorkspaceFolders(new DidChangeWorkspaceFoldersParams => [ | ||
event = new WorkspaceFoldersChangeEvent => [ | ||
added = #[ | ||
new WorkspaceFolder(rootFolder2.toURI.toUriString, 'root2') | ||
] | ||
] | ||
]) | ||
] | ||
assertEquals(1, diagnostics.get(twoUri).size) | ||
} | ||
|
||
protected def void withBuild(()=>void lambda) { | ||
val future = new CompletableFuture<Void>() | ||
workspaceManager.addBuildListener[ | ||
workspaceManager.removeBuildListener(self) | ||
future.complete(null) | ||
] | ||
lambda.apply | ||
future.get | ||
} | ||
|
||
protected def getRoot(String path) { | ||
val root = new File(path) | ||
if (!root.mkdirs) { | ||
Files.cleanFolder(root, null, true, false) | ||
} | ||
root.deleteOnExit | ||
root | ||
} | ||
|
||
def String writeFile(File root, String path, CharSequence contents) { | ||
val file = new File(root, path) | ||
file.parentFile.mkdirs | ||
file.createNewFile | ||
|
||
val writer = new FileWriter(file) | ||
writer.write(contents.toString) | ||
writer.close | ||
|
||
return file.toURI.normalize.toUriString | ||
} | ||
|
||
override protected getServerModule() { | ||
val defaultModule = super.getServerModule() | ||
val Module customModule = new AbstractModule() { | ||
override protected configure() { | ||
bind(WorkspaceManager).in(Scopes.SINGLETON); | ||
} | ||
} | ||
return Modules2.mixin(defaultModule, customModule) | ||
} | ||
|
||
} |
182 changes: 182 additions & 0 deletions
182
...se.xtext.ide.tests/xtend-gen/org/eclipse/xtext/ide/tests/server/WorkspaceFoldersTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
/** | ||
* Copyright (c) 2020 TypeFox GmbH (http://www.typefox.io) and others. | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*/ | ||
package org.eclipse.xtext.ide.tests.server; | ||
|
||
import com.google.inject.AbstractModule; | ||
import com.google.inject.Inject; | ||
import com.google.inject.Scopes; | ||
import java.io.File; | ||
import java.io.FileWriter; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.concurrent.CompletableFuture; | ||
import org.eclipse.lsp4j.DidChangeWorkspaceFoldersParams; | ||
import org.eclipse.lsp4j.InitializeParams; | ||
import org.eclipse.lsp4j.WorkspaceFolder; | ||
import org.eclipse.lsp4j.WorkspaceFoldersChangeEvent; | ||
import org.eclipse.xtend2.lib.StringConcatenation; | ||
import org.eclipse.xtext.ide.server.ILanguageServerAccess; | ||
import org.eclipse.xtext.ide.server.UriExtensions; | ||
import org.eclipse.xtext.ide.server.WorkspaceManager; | ||
import org.eclipse.xtext.ide.tests.server.AbstractTestLangLanguageServerTest; | ||
import org.eclipse.xtext.resource.IResourceDescription; | ||
import org.eclipse.xtext.util.Files; | ||
import org.eclipse.xtext.util.Modules2; | ||
import org.eclipse.xtext.xbase.lib.CollectionLiterals; | ||
import org.eclipse.xtext.xbase.lib.Exceptions; | ||
import org.eclipse.xtext.xbase.lib.Extension; | ||
import org.eclipse.xtext.xbase.lib.ObjectExtensions; | ||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure0; | ||
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1; | ||
import org.junit.Assert; | ||
import org.junit.Test; | ||
|
||
/** | ||
* @author Jan Koehnlein - Initial contribution and API | ||
*/ | ||
@SuppressWarnings("all") | ||
public class WorkspaceFoldersTest extends AbstractTestLangLanguageServerTest { | ||
@Inject | ||
@Extension | ||
private UriExtensions _uriExtensions; | ||
|
||
@Inject | ||
private WorkspaceManager workspaceManager; | ||
|
||
@Test | ||
public void testInitialize() { | ||
final File rootFolder1 = this.getRoot("root1"); | ||
final File rootFolder2 = this.getRoot("root2"); | ||
StringConcatenation _builder = new StringConcatenation(); | ||
_builder.append("type Foo {"); | ||
_builder.newLine(); | ||
_builder.append("\t"); | ||
_builder.append("Bar bar"); | ||
_builder.newLine(); | ||
_builder.append("}"); | ||
_builder.newLine(); | ||
this.writeFile(rootFolder1, "one.testlang", _builder); | ||
StringConcatenation _builder_1 = new StringConcatenation(); | ||
_builder_1.append("type Bar {"); | ||
_builder_1.newLine(); | ||
_builder_1.append("\t"); | ||
_builder_1.append("Foo foo"); | ||
_builder_1.newLine(); | ||
_builder_1.append("}"); | ||
_builder_1.newLine(); | ||
final String twoUri = this.writeFile(rootFolder2, "two.testlang", _builder_1); | ||
final Procedure1<InitializeParams> _function = (InitializeParams it) -> { | ||
String _uriString = this._uriExtensions.toUriString(rootFolder1.toURI()); | ||
WorkspaceFolder _workspaceFolder = new WorkspaceFolder(_uriString, "root1"); | ||
String _uriString_1 = this._uriExtensions.toUriString(rootFolder2.toURI()); | ||
WorkspaceFolder _workspaceFolder_1 = new WorkspaceFolder(_uriString_1, "root2"); | ||
it.setWorkspaceFolders(Collections.<WorkspaceFolder>unmodifiableList(CollectionLiterals.<WorkspaceFolder>newArrayList(_workspaceFolder, _workspaceFolder_1))); | ||
}; | ||
this.initialize(_function); | ||
Assert.assertEquals(2, this.getDiagnostics().size()); | ||
Assert.assertEquals(1, this.getDiagnostics().get(twoUri).size()); | ||
final Procedure0 _function_1 = () -> { | ||
DidChangeWorkspaceFoldersParams _didChangeWorkspaceFoldersParams = new DidChangeWorkspaceFoldersParams(); | ||
final Procedure1<DidChangeWorkspaceFoldersParams> _function_2 = (DidChangeWorkspaceFoldersParams it) -> { | ||
WorkspaceFoldersChangeEvent _workspaceFoldersChangeEvent = new WorkspaceFoldersChangeEvent(); | ||
final Procedure1<WorkspaceFoldersChangeEvent> _function_3 = (WorkspaceFoldersChangeEvent it_1) -> { | ||
String _uriString = this._uriExtensions.toUriString(rootFolder2.toURI()); | ||
WorkspaceFolder _workspaceFolder = new WorkspaceFolder(_uriString, "root2"); | ||
it_1.setRemoved(Collections.<WorkspaceFolder>unmodifiableList(CollectionLiterals.<WorkspaceFolder>newArrayList(_workspaceFolder))); | ||
}; | ||
WorkspaceFoldersChangeEvent _doubleArrow = ObjectExtensions.<WorkspaceFoldersChangeEvent>operator_doubleArrow(_workspaceFoldersChangeEvent, _function_3); | ||
it.setEvent(_doubleArrow); | ||
}; | ||
DidChangeWorkspaceFoldersParams _doubleArrow = ObjectExtensions.<DidChangeWorkspaceFoldersParams>operator_doubleArrow(_didChangeWorkspaceFoldersParams, _function_2); | ||
this.languageServer.didChangeWorkspaceFolders(_doubleArrow); | ||
}; | ||
this.withBuild(_function_1); | ||
Assert.assertEquals(0, this.getDiagnostics().get(twoUri).size()); | ||
final Procedure0 _function_2 = () -> { | ||
DidChangeWorkspaceFoldersParams _didChangeWorkspaceFoldersParams = new DidChangeWorkspaceFoldersParams(); | ||
final Procedure1<DidChangeWorkspaceFoldersParams> _function_3 = (DidChangeWorkspaceFoldersParams it) -> { | ||
WorkspaceFoldersChangeEvent _workspaceFoldersChangeEvent = new WorkspaceFoldersChangeEvent(); | ||
final Procedure1<WorkspaceFoldersChangeEvent> _function_4 = (WorkspaceFoldersChangeEvent it_1) -> { | ||
String _uriString = this._uriExtensions.toUriString(rootFolder2.toURI()); | ||
WorkspaceFolder _workspaceFolder = new WorkspaceFolder(_uriString, "root2"); | ||
it_1.setAdded(Collections.<WorkspaceFolder>unmodifiableList(CollectionLiterals.<WorkspaceFolder>newArrayList(_workspaceFolder))); | ||
}; | ||
WorkspaceFoldersChangeEvent _doubleArrow = ObjectExtensions.<WorkspaceFoldersChangeEvent>operator_doubleArrow(_workspaceFoldersChangeEvent, _function_4); | ||
it.setEvent(_doubleArrow); | ||
}; | ||
DidChangeWorkspaceFoldersParams _doubleArrow = ObjectExtensions.<DidChangeWorkspaceFoldersParams>operator_doubleArrow(_didChangeWorkspaceFoldersParams, _function_3); | ||
this.languageServer.didChangeWorkspaceFolders(_doubleArrow); | ||
}; | ||
this.withBuild(_function_2); | ||
Assert.assertEquals(1, this.getDiagnostics().get(twoUri).size()); | ||
} | ||
|
||
protected void withBuild(final Procedure0 lambda) { | ||
try { | ||
final CompletableFuture<Void> future = new CompletableFuture<Void>(); | ||
final ILanguageServerAccess.IBuildListener _function = new ILanguageServerAccess.IBuildListener() { | ||
@Override | ||
public void afterBuild(final List<IResourceDescription.Delta> it) { | ||
WorkspaceFoldersTest.this.workspaceManager.removeBuildListener(this); | ||
future.complete(null); | ||
} | ||
}; | ||
this.workspaceManager.addBuildListener(_function); | ||
lambda.apply(); | ||
future.get(); | ||
} catch (Throwable _e) { | ||
throw Exceptions.sneakyThrow(_e); | ||
} | ||
} | ||
|
||
protected File getRoot(final String path) { | ||
try { | ||
File _xblockexpression = null; | ||
{ | ||
final File root = new File(path); | ||
boolean _mkdirs = root.mkdirs(); | ||
boolean _not = (!_mkdirs); | ||
if (_not) { | ||
Files.cleanFolder(root, null, true, false); | ||
} | ||
root.deleteOnExit(); | ||
_xblockexpression = root; | ||
} | ||
return _xblockexpression; | ||
} catch (Throwable _e) { | ||
throw Exceptions.sneakyThrow(_e); | ||
} | ||
} | ||
|
||
public String writeFile(final File root, final String path, final CharSequence contents) { | ||
try { | ||
final File file = new File(root, path); | ||
file.getParentFile().mkdirs(); | ||
file.createNewFile(); | ||
final FileWriter writer = new FileWriter(file); | ||
writer.write(contents.toString()); | ||
writer.close(); | ||
return this._uriExtensions.toUriString(file.toURI().normalize()); | ||
} catch (Throwable _e) { | ||
throw Exceptions.sneakyThrow(_e); | ||
} | ||
} | ||
|
||
@Override | ||
protected com.google.inject.Module getServerModule() { | ||
final com.google.inject.Module defaultModule = super.getServerModule(); | ||
final com.google.inject.Module customModule = new AbstractModule() { | ||
@Override | ||
protected void configure() { | ||
this.<WorkspaceManager>bind(WorkspaceManager.class).in(Scopes.SINGLETON); | ||
} | ||
}; | ||
return Modules2.mixin(defaultModule, customModule); | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/server/IMultiRootWorkspaceConfigFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2020 TypeFox GmbH (http://www.typefox.io) and others. | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*******************************************************************************/ | ||
package org.eclipse.xtext.ide.server; | ||
|
||
import java.util.List; | ||
|
||
import org.eclipse.lsp4j.WorkspaceFolder; | ||
import org.eclipse.xtext.workspace.IWorkspaceConfig; | ||
|
||
/** | ||
* @author Jan Koehnlein - Initial contribution and API | ||
* @since 2.11 | ||
*/ | ||
public interface IMultiRootWorkspaceConfigFactory { | ||
|
||
/** | ||
* Create a workspace config at the given location. | ||
* | ||
* @param workspaceFolders the list of workspace root folders | ||
* @return the workspace configuration. | ||
*/ | ||
IWorkspaceConfig getWorkspaceConfig(List<WorkspaceFolder> workspaceFolders); | ||
|
||
} |
Oops, something went wrong.