Merge pull request #395 from eclipse/se_codelens

[lsp] added hooks for code lenses and language specific capabalities
This commit is contained in:
Sven Efftinge 2017-07-18 09:53:37 +02:00 committed by GitHub
commit 3627b52a6b
22 changed files with 879 additions and 193 deletions

View file

@ -0,0 +1,33 @@
/*******************************************************************************
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* 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
*******************************************************************************/
package org.eclipse.xtext.ide.tests.server
import org.eclipse.lsp4j.Position
import org.junit.Assert
import org.junit.Test
/**
* @author Sven Efftinge - Initial contribution and API
*/
class CodeLensTest extends AbstractTestLangLanguageServerTest {
@Test def void testCodeLens() {
testCodeLens [
model = '''
type Foo {}
type Bar {
Foo foo
}
'''
assertCodeLenses = [
assertEquals("Do Awesome Stuff(RESOLVED)", head.command.title)
Assert.assertEquals(1, (head.data as Position).line)
]
]
}
}

View file

@ -8,6 +8,9 @@
package org.eclipse.xtext.ide.tests.testlanguage.ide
import org.eclipse.xtext.ide.server.ILanguageServerExtension
import org.eclipse.xtext.ide.server.codelens.ICodeLensResolver
import org.eclipse.xtext.ide.tests.testlanguage.scoping.CodeLensProvider
import org.eclipse.xtext.ide.server.codelens.ICodeLensService
/**
* Use this class to register ide components.
@ -18,4 +21,12 @@ class TestLanguageIdeModule extends AbstractTestLanguageIdeModule {
TestLangLSPExtension
}
def Class<? extends ICodeLensResolver> bindICodeLensResolver() {
CodeLensProvider
}
def Class<? extends ICodeLensService> bindICodeLensService() {
CodeLensProvider
}
}

View file

@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* 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
*******************************************************************************/
package org.eclipse.xtext.ide.tests.testlanguage.scoping
import org.eclipse.xtext.ide.server.codelens.ICodeLensService
import org.eclipse.xtext.ide.server.codelens.ICodeLensResolver
import org.eclipse.xtext.ide.server.Document
import org.eclipse.xtext.resource.XtextResource
import org.eclipse.lsp4j.CodeLensParams
import org.eclipse.xtext.util.CancelIndicator
import org.eclipse.lsp4j.CodeLens
import org.eclipse.lsp4j.Command
import org.eclipse.lsp4j.Position
/**
* @author Sven Efftinge - Initial contribution and API
*/
class CodeLensProvider implements ICodeLensService, ICodeLensResolver {
override computeCodeLenses(Document document, XtextResource resource, CodeLensParams params, CancelIndicator indicator) {
return #[new CodeLens() => [
command = new Command() => [
command = "do.this"
title = "Do Awesome Stuff"
arguments = #[
'foo',
1,
true
]
]
data = new Position(1,2)
]]
}
override resolveCodeLens(Document document, XtextResource resource, CodeLens codeLens, CancelIndicator indicator) {
codeLens.command.title = codeLens.command.title + "(RESOLVED)"
return codeLens
}
}

View file

@ -0,0 +1,49 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* 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
*/
package org.eclipse.xtext.ide.tests.server;
import java.util.List;
import org.eclipse.lsp4j.CodeLens;
import org.eclipse.lsp4j.Position;
import org.eclipse.xtend2.lib.StringConcatenation;
import org.eclipse.xtext.ide.tests.server.AbstractTestLangLanguageServerTest;
import org.eclipse.xtext.testing.AbstractLanguageServerTest;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.junit.Assert;
import org.junit.Test;
/**
* @author Sven Efftinge - Initial contribution and API
*/
@SuppressWarnings("all")
public class CodeLensTest extends AbstractTestLangLanguageServerTest {
@Test
public void testCodeLens() {
final Procedure1<AbstractLanguageServerTest.TestCodeLensConfiguration> _function = (AbstractLanguageServerTest.TestCodeLensConfiguration it) -> {
StringConcatenation _builder = new StringConcatenation();
_builder.append("type Foo {}");
_builder.newLine();
_builder.append("type Bar {");
_builder.newLine();
_builder.append("\t");
_builder.append("Foo foo");
_builder.newLine();
_builder.append("}");
_builder.newLine();
it.setModel(_builder.toString());
final Procedure1<List<? extends CodeLens>> _function_1 = (List<? extends CodeLens> it_1) -> {
this.assertEquals("Do Awesome Stuff(RESOLVED)", IterableExtensions.head(it_1).getCommand().getTitle());
Object _data = IterableExtensions.head(it_1).getData();
Assert.assertEquals(1, ((Position) _data).getLine());
};
it.setAssertCodeLenses(_function_1);
};
this.testCodeLens(_function);
}
}

View file

@ -8,8 +8,11 @@
package org.eclipse.xtext.ide.tests.testlanguage.ide;
import org.eclipse.xtext.ide.server.ILanguageServerExtension;
import org.eclipse.xtext.ide.server.codelens.ICodeLensResolver;
import org.eclipse.xtext.ide.server.codelens.ICodeLensService;
import org.eclipse.xtext.ide.tests.testlanguage.ide.AbstractTestLanguageIdeModule;
import org.eclipse.xtext.ide.tests.testlanguage.ide.TestLangLSPExtension;
import org.eclipse.xtext.ide.tests.testlanguage.scoping.CodeLensProvider;
/**
* Use this class to register ide components.
@ -19,4 +22,12 @@ public class TestLanguageIdeModule extends AbstractTestLanguageIdeModule {
public Class<? extends ILanguageServerExtension> bindLanguageServerExtension() {
return TestLangLSPExtension.class;
}
public Class<? extends ICodeLensResolver> bindICodeLensResolver() {
return CodeLensProvider.class;
}
public Class<? extends ICodeLensService> bindICodeLensService() {
return CodeLensProvider.class;
}
}

View file

@ -0,0 +1,57 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* 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
*/
package org.eclipse.xtext.ide.tests.testlanguage.scoping;
import java.util.Collections;
import java.util.List;
import org.eclipse.lsp4j.CodeLens;
import org.eclipse.lsp4j.CodeLensParams;
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.Position;
import org.eclipse.xtext.ide.server.Document;
import org.eclipse.xtext.ide.server.codelens.ICodeLensResolver;
import org.eclipse.xtext.ide.server.codelens.ICodeLensService;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.util.CancelIndicator;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
/**
* @author Sven Efftinge - Initial contribution and API
*/
@SuppressWarnings("all")
public class CodeLensProvider implements ICodeLensService, ICodeLensResolver {
@Override
public List<? extends CodeLens> computeCodeLenses(final Document document, final XtextResource resource, final CodeLensParams params, final CancelIndicator indicator) {
CodeLens _codeLens = new CodeLens();
final Procedure1<CodeLens> _function = (CodeLens it) -> {
Command _command = new Command();
final Procedure1<Command> _function_1 = (Command it_1) -> {
it_1.setCommand("do.this");
it_1.setTitle("Do Awesome Stuff");
it_1.setArguments(Collections.<Object>unmodifiableList(CollectionLiterals.<Object>newArrayList("foo", Integer.valueOf(1), Boolean.valueOf(true))));
};
Command _doubleArrow = ObjectExtensions.<Command>operator_doubleArrow(_command, _function_1);
it.setCommand(_doubleArrow);
Position _position = new Position(1, 2);
it.setData(_position);
};
CodeLens _doubleArrow = ObjectExtensions.<CodeLens>operator_doubleArrow(_codeLens, _function);
return Collections.<CodeLens>unmodifiableList(CollectionLiterals.<CodeLens>newArrayList(_doubleArrow));
}
@Override
public CodeLens resolveCodeLens(final Document document, final XtextResource resource, final CodeLens codeLens, final CancelIndicator indicator) {
Command _command = codeLens.getCommand();
String _title = codeLens.getCommand().getTitle();
String _plus = (_title + "(RESOLVED)");
_command.setTitle(_plus);
return codeLens;
}
}

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* 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
*******************************************************************************/
package org.eclipse.xtext.ide.server
import org.eclipse.lsp4j.ServerCapabilities
import org.eclipse.lsp4j.InitializeParams
/**
* @author Sven Efftinge - Initial contribution and API
*/
interface ICapabilitiesContributor {
/**
* Allows an individual language to contribute to and overwrite properties in the server's capabilities.
*/
def ServerCapabilities contribute(ServerCapabilities capabilities, InitializeParams params);
}

View file

@ -17,6 +17,7 @@ import java.util.function.Function
import org.eclipse.emf.common.util.URI
import org.eclipse.lsp4j.CodeActionParams
import org.eclipse.lsp4j.CodeLens
import org.eclipse.lsp4j.CodeLensOptions
import org.eclipse.lsp4j.CodeLensParams
import org.eclipse.lsp4j.ColoringParams
import org.eclipse.lsp4j.CompletionItem
@ -63,12 +64,14 @@ import org.eclipse.lsp4j.services.TextDocumentService
import org.eclipse.lsp4j.services.WorkspaceService
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
import org.eclipse.xtext.ide.server.ILanguageServerAccess.IBuildListener
import org.eclipse.xtext.ide.server.codelens.ICodeLensResolver
import org.eclipse.xtext.ide.server.codelens.ICodeLensService
import org.eclipse.xtext.ide.server.coloring.IColoringService
import org.eclipse.xtext.ide.server.concurrent.RequestManager
import org.eclipse.xtext.ide.server.contentassist.ContentAssistService
import org.eclipse.xtext.ide.server.findReferences.WorkspaceResourceAccess
import org.eclipse.xtext.ide.server.formatting.FormattingService
import org.eclipse.xtext.ide.server.hover.HoverService
import org.eclipse.xtext.ide.server.hover.IHoverService
import org.eclipse.xtext.ide.server.occurrences.IDocumentHighlightService
import org.eclipse.xtext.ide.server.signatureHelp.ISignatureHelpService
import org.eclipse.xtext.ide.server.symbol.DocumentSymbolService
@ -100,6 +103,13 @@ import org.eclipse.xtext.validation.Issue
this.workspaceManager = manager
resourceAccess = new WorkspaceResourceAccess(workspaceManager)
}
private def Iterable<? extends IResourceServiceProvider> getAllLanguages() {
this.languagesRegistry.extensionToFactoryMap.keySet.toList.sort.map[ext|
val synthUri = URI.createURI("synth:///file."+ext)
return synthUri.resourceServiceProvider
]
}
override CompletableFuture<InitializeResult> initialize(InitializeParams params) {
if (this.params !== null) {
@ -111,13 +121,20 @@ import org.eclipse.xtext.validation.Issue
}
this.params = params
val result = new InitializeResult
result.capabilities = new ServerCapabilities => [
var capabilities = new ServerCapabilities => [
hoverProvider = true
definitionProvider = true
referencesProvider = true
documentSymbolProvider = true
workspaceSymbolProvider = true
//TODO make this language specific
// check if a language with code lens capability exists
if (allLanguages.exists[get(ICodeLensService)!==null]) {
codeLensProvider = new CodeLensOptions => [
resolveProvider = allLanguages.exists[get(ICodeLensResolver)!==null]
]
}
signatureHelpProvider = new SignatureHelpOptions(#['(', ','])
textDocumentSync = TextDocumentSyncKind.Incremental
completionProvider = new CompletionOptions => [
@ -128,7 +145,11 @@ import org.eclipse.xtext.validation.Issue
documentRangeFormattingProvider = true
documentHighlightProvider = true
]
for (language : allLanguages) {
language.get(ICapabilitiesContributor)?.contribute(capabilities, params)
}
result.capabilities = capabilities
requestManager.lockWrite [
workspaceManager.initialize(baseDir, [this.publishDiagnostics($0, $1)], CancelIndicator.NullImpl)
return null
@ -362,9 +383,9 @@ import org.eclipse.xtext.validation.Issue
return requestManager.runRead[ cancelIndicator |
val uri = params.textDocument.uri.toUri
val resourceServiceProvider = uri.resourceServiceProvider
val hoverService = resourceServiceProvider?.get(HoverService)
val hoverService = resourceServiceProvider?.get(IHoverService)
if (hoverService === null)
return HoverService.EMPTY_HOVER
return IHoverService.EMPTY_HOVER
return workspaceManager.doRead(uri) [ document, resource |
hoverService.hover(document, resource, params, cancelIndicator)
@ -409,13 +430,62 @@ import org.eclipse.xtext.validation.Issue
override codeAction(CodeActionParams params) {
throw new UnsupportedOperationException("TODO: auto-generated method stub")
}
private def void installURI(List<? extends CodeLens> codeLenses, String uri) {
for (lens : codeLenses) {
if (lens.data !== null) {
lens.data = newArrayList(uri, lens.data)
} else {
lens.data = uri
}
}
}
private def URI uninstallURI(CodeLens lens) {
var URI result = null
if (lens.data instanceof String) {
result = URI.createURI(lens.data.toString)
lens.data = null
} else if (lens.data instanceof List<?>) {
val l = lens.data as List<?>
result = URI.createURI(l.head.toString)
lens.data = l.get(1)
}
return result
}
override codeLens(CodeLensParams params) {
throw new UnsupportedOperationException("TODO: auto-generated method stub")
return requestManager.runRead[ cancelIndicator |
val uri = params.textDocument.uri.toUri
val resourceServiceProvider = uri.resourceServiceProvider
val codeLensService = resourceServiceProvider?.get(ICodeLensService)
if (codeLensService === null)
return emptyList
return workspaceManager.doRead(uri) [ document, resource |
val result = codeLensService.computeCodeLenses(document, resource, params, cancelIndicator)
installURI(result, uri.toString)
return result
]
]
}
override resolveCodeLens(CodeLens unresolved) {
return CompletableFuture.completedFuture(unresolved)
val uri = uninstallURI(unresolved)
if (uri === null) {
return CompletableFuture.completedFuture(unresolved)
}
return requestManager.runRead[ cancelIndicator |
val resourceServiceProvider = uri.resourceServiceProvider
val resolver = resourceServiceProvider?.get(ICodeLensResolver)
if (resolver === null)
return unresolved
return workspaceManager.doRead(uri) [ document, resource |
val result = resolver.resolveCodeLens(document, resource, unresolved, cancelIndicator)
return result
]
]
}
override formatting(DocumentFormattingParams params) {

View file

@ -38,96 +38,98 @@ import org.eclipse.xtext.workspace.IWorkspaceConfig
* @since 2.11
*/
@Log class WorkspaceManager {
@Inject Provider<ProjectManager> projectManagerProvider
@Inject IWorkspaceConfigFactory workspaceConfigFactory
@Inject IProjectDescriptionFactory projectDescriptionFactory
BuildManager buildManager
Map<String, ProjectManager> projectName2ProjectManager = newHashMap
URI baseDir
(URI, Iterable<Issue>)=>void issueAcceptor
IWorkspaceConfig _workspaceConfig
List<IBuildListener> buildListeners = newArrayList
def void addBuildListener(IBuildListener listener) {
this.buildListeners += listener
}
Map<String, ResourceDescriptionsData> fullIndex = newHashMap()
Map<URI, Document> openDocuments = newHashMap()
val openedDocumentsContentProvider = new IExternalContentProvider() {
@Inject Provider<ProjectManager> projectManagerProvider
@Inject IWorkspaceConfigFactory workspaceConfigFactory
@Inject IProjectDescriptionFactory projectDescriptionFactory
BuildManager buildManager
override getActualContentProvider() {
return this
}
Map<String, ProjectManager> projectName2ProjectManager = newHashMap
override getContent(URI uri) {
openDocuments.get(uri)?.contents
}
URI baseDir
(URI, Iterable<Issue>)=>void issueAcceptor
IWorkspaceConfig _workspaceConfig
override hasContent(URI uri) {
openDocuments.containsKey(uri)
}
};
@Inject
def void setBuildManager(BuildManager buildManager) {
buildManager.workspaceManager = this
this.buildManager = buildManager
}
def void initialize(URI baseDir, (URI, Iterable<Issue>)=>void issueAcceptor, CancelIndicator cancelIndicator) {
this.baseDir = baseDir
this.issueAcceptor = issueAcceptor
refreshWorkspaceConfig(cancelIndicator)
}
protected def void refreshWorkspaceConfig(CancelIndicator cancelIndicator) {
workspaceConfig = workspaceConfigFactory.getWorkspaceConfig(baseDir)
val newProjects = newArrayList
val Set<String> remainingProjectNames = new HashSet(projectName2ProjectManager.keySet)
workspaceConfig.projects.forEach [ projectConfig |
if(projectName2ProjectManager.containsKey(projectConfig.name)) {
remainingProjectNames.remove(projectConfig.name)
} else {
val projectManager = projectManagerProvider.get
val projectDescription = projectDescriptionFactory.getProjectDescription(projectConfig)
projectManager.initialize(projectDescription, projectConfig, issueAcceptor, openedDocumentsContentProvider, [fullIndex], cancelIndicator)
projectName2ProjectManager.put(projectDescription.name, projectManager)
newProjects.add(projectDescription)
}
]
for(deletedProject: remainingProjectNames) {
projectName2ProjectManager.remove(deletedProject)
fullIndex.remove(deletedProject)
}
val result = buildManager.doInitialBuild(newProjects, cancelIndicator)
afterBuild(result)
}
protected def IWorkspaceConfig getWorkspaceConfig() {
if (_workspaceConfig === null) {
val error = new ResponseError(ResponseErrorCode.serverNotInitialized, "Workspace has not been initialized yet.", null)
throw new ResponseErrorException(error)
List<IBuildListener> buildListeners = newArrayList
def void addBuildListener(IBuildListener listener) {
this.buildListeners += listener
}
Map<String, ResourceDescriptionsData> fullIndex = newHashMap()
Map<URI, Document> openDocuments = newHashMap()
val openedDocumentsContentProvider = new IExternalContentProvider() {
override getActualContentProvider() {
return this
}
override getContent(URI uri) {
openDocuments.get(uri)?.contents
}
override hasContent(URI uri) {
openDocuments.containsKey(uri)
}
};
@Inject
def void setBuildManager(BuildManager buildManager) {
buildManager.workspaceManager = this
this.buildManager = buildManager
}
def void initialize(URI baseDir, (URI, Iterable<Issue>)=>void issueAcceptor, CancelIndicator cancelIndicator) {
this.baseDir = baseDir
this.issueAcceptor = issueAcceptor
refreshWorkspaceConfig(cancelIndicator)
}
protected def void refreshWorkspaceConfig(CancelIndicator cancelIndicator) {
workspaceConfig = workspaceConfigFactory.getWorkspaceConfig(baseDir)
val newProjects = newArrayList
val Set<String> remainingProjectNames = new HashSet(projectName2ProjectManager.keySet)
workspaceConfig.projects.forEach [ projectConfig |
if (projectName2ProjectManager.containsKey(projectConfig.name)) {
remainingProjectNames.remove(projectConfig.name)
} else {
val projectManager = projectManagerProvider.get
val projectDescription = projectDescriptionFactory.getProjectDescription(projectConfig)
projectManager.initialize(projectDescription, projectConfig, issueAcceptor,
openedDocumentsContentProvider, [fullIndex], cancelIndicator)
projectName2ProjectManager.put(projectDescription.name, projectManager)
newProjects.add(projectDescription)
}
]
for (deletedProject : remainingProjectNames) {
projectName2ProjectManager.remove(deletedProject)
fullIndex.remove(deletedProject)
}
val result = buildManager.doInitialBuild(newProjects, cancelIndicator)
afterBuild(result)
}
protected def IWorkspaceConfig getWorkspaceConfig() {
if (_workspaceConfig === null) {
val error = new ResponseError(ResponseErrorCode.serverNotInitialized,
"Workspace has not been initialized yet.", null)
throw new ResponseErrorException(error)
}
return _workspaceConfig
}
protected def void setWorkspaceConfig(IWorkspaceConfig workspaceConfig) {
this._workspaceConfig = workspaceConfig
}
}
protected def void setWorkspaceConfig(IWorkspaceConfig workspaceConfig) {
this._workspaceConfig = workspaceConfig
}
protected def void afterBuild(List<Delta> deltas) {
for (listener : buildListeners) {
listener.afterBuild(deltas)
}
}
def Buildable didChangeFiles(List<URI> dirtyFiles, List<URI> deletedFiles) {
val buildable = buildManager.submit(dirtyFiles, deletedFiles)
return [ cancelIndicator |
@ -137,90 +139,90 @@ import org.eclipse.xtext.workspace.IWorkspaceConfig
]
}
def List<IResourceDescription.Delta> doBuild(List<URI> dirtyFiles, List<URI> deletedFiles, CancelIndicator cancelIndicator) {
return didChangeFiles(dirtyFiles, deletedFiles).build(cancelIndicator)
}
def IResourceDescriptions getIndex() {
return new ChunkedResourceDescriptions(fullIndex)
}
def List<IResourceDescription.Delta> doBuild(List<URI> dirtyFiles, List<URI> deletedFiles,
CancelIndicator cancelIndicator) {
return didChangeFiles(dirtyFiles, deletedFiles).build(cancelIndicator)
}
def URI getProjectBaseDir(URI uri) {
val projectConfig = workspaceConfig.findProjectContaining(uri)
return projectConfig?.path
}
def ProjectManager getProjectManager(URI uri) {
val projectConfig = workspaceConfig.findProjectContaining(uri)
return projectName2ProjectManager.get(projectConfig?.name)
}
def ProjectManager getProjectManager(String projectName) {
projectName2ProjectManager.get(projectName)
}
def List<ProjectManager> getProjectManagers() {
new ArrayList(projectName2ProjectManager.values)
}
def IResourceDescriptions getIndex() {
return new ChunkedResourceDescriptions(fullIndex)
}
def didChange(URI uri, int version, Iterable<TextEdit> changes, CancelIndicator cancelIndicator) {
didChange(uri, version, changes).build(cancelIndicator)
}
def URI getProjectBaseDir(URI uri) {
val projectConfig = workspaceConfig.findProjectContaining(uri)
return projectConfig?.path
}
def Buildable didChange(URI uri, int version, Iterable<TextEdit> changes) {
if (!openDocuments.containsKey(uri)) {
LOG.error("The document "+uri+" has not been opened.")
return [];
}
val contents = openDocuments.get(uri)
openDocuments.put(uri, contents.applyChanges(changes))
return didChangeFiles(#[uri], newArrayList)
}
def didOpen(URI uri, int version, String contents, CancelIndicator cancelIndicator) {
didOpen(uri, version, contents).build(cancelIndicator)
}
def Buildable didOpen(URI uri, int version, String contents) {
openDocuments.put(uri, new Document(version, contents))
return didChangeFiles(#[uri], newArrayList)
}
def didClose(URI uri, CancelIndicator cancelIndicator) {
didClose(uri).build(cancelIndicator)
}
def Buildable didClose(URI uri) {
openDocuments.remove(uri)
if (exists(uri)) {
return didChangeFiles(#[uri], newArrayList)
}
return didChangeFiles(newArrayList, #[uri])
}
protected def boolean exists(URI uri) {
val rs = getProjectManager(uri)?.resourceSet
if (rs === null)
return false
return rs.URIConverter.exists(uri, null)
}
def <T> T doRead(URI uri, (Document, XtextResource)=>T work) {
val resourceURI = uri.trimFragment
val projectMnr = getProjectManager(resourceURI)
val resource = projectMnr?.getResource(resourceURI) as XtextResource
if (resource === null) {
return work.apply(null, null)
}
var doc = getDocument(resource)
return work.apply(doc, projectMnr.getResource(resourceURI) as XtextResource)
}
protected def Document getDocument(XtextResource resource) {
return openDocuments.get(resource.URI)
// lets create a transient document, in case a document is not open (e.g. formatting is called just by uri)
?: new Document(1, resource.parseResult.rootNode.text)
}
def ProjectManager getProjectManager(URI uri) {
val projectConfig = workspaceConfig.findProjectContaining(uri)
return projectName2ProjectManager.get(projectConfig?.name)
}
def ProjectManager getProjectManager(String projectName) {
projectName2ProjectManager.get(projectName)
}
def List<ProjectManager> getProjectManagers() {
new ArrayList(projectName2ProjectManager.values)
}
def didChange(URI uri, int version, Iterable<TextEdit> changes, CancelIndicator cancelIndicator) {
didChange(uri, version, changes).build(cancelIndicator)
}
def Buildable didChange(URI uri, int version, Iterable<TextEdit> changes) {
if (!openDocuments.containsKey(uri)) {
LOG.error("The document " + uri + " has not been opened.")
return [];
}
val contents = openDocuments.get(uri)
openDocuments.put(uri, contents.applyChanges(changes))
return didChangeFiles(#[uri], newArrayList)
}
def didOpen(URI uri, int version, String contents, CancelIndicator cancelIndicator) {
didOpen(uri, version, contents).build(cancelIndicator)
}
def Buildable didOpen(URI uri, int version, String contents) {
openDocuments.put(uri, new Document(version, contents))
return didChangeFiles(#[uri], newArrayList)
}
def didClose(URI uri, CancelIndicator cancelIndicator) {
didClose(uri).build(cancelIndicator)
}
def Buildable didClose(URI uri) {
openDocuments.remove(uri)
if (exists(uri)) {
return didChangeFiles(#[uri], newArrayList)
}
return didChangeFiles(newArrayList, #[uri])
}
protected def boolean exists(URI uri) {
val rs = getProjectManager(uri)?.resourceSet
if (rs === null)
return false
return rs.URIConverter.exists(uri, null)
}
def <T> T doRead(URI uri, (Document, XtextResource)=>T work) {
val resourceURI = uri.trimFragment
val projectMnr = getProjectManager(resourceURI)
val resource = projectMnr?.getResource(resourceURI) as XtextResource
if (resource === null) {
return work.apply(null, null)
}
var doc = getDocument(resource)
return work.apply(doc, projectMnr.getResource(resourceURI) as XtextResource)
}
protected def Document getDocument(XtextResource resource) {
return openDocuments.get(resource.URI) // lets create a transient document, in case a document is not open (e.g. formatting is called just by uri)
?: new Document(1, resource.parseResult.rootNode.text)
}
public def boolean isDocumentOpen(URI uri) {
return openDocuments.containsKey(uri)

View file

@ -0,0 +1,24 @@
/*******************************************************************************
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* 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
*******************************************************************************/
package org.eclipse.xtext.ide.server.codelens
import org.eclipse.lsp4j.CodeLens
import org.eclipse.xtext.ide.server.Document
import org.eclipse.xtext.resource.XtextResource
import org.eclipse.xtext.util.CancelIndicator
/**
* @author Sven Efftinge - Initial contribution and API
*/
interface ICodeLensResolver {
/**
* Resolve the given code lens.
*/
def CodeLens resolveCodeLens(Document document, XtextResource resource, CodeLens codeLens, CancelIndicator indicator);
}

View file

@ -0,0 +1,27 @@
/*******************************************************************************
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* 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
*******************************************************************************/
package org.eclipse.xtext.ide.server.codelens
import java.util.List
import org.eclipse.lsp4j.CodeLens
import org.eclipse.lsp4j.CodeLensParams
import org.eclipse.xtext.ide.server.Document
import org.eclipse.xtext.resource.XtextResource
import org.eclipse.xtext.util.CancelIndicator
/**
* @author Sven Efftinge - Initial contribution and API
*/
interface ICodeLensService {
/**
* compute code lenses for the given context.
*/
def List<? extends CodeLens> computeCodeLenses(Document document, XtextResource resource, CodeLensParams params, CancelIndicator indicator);
}

View file

@ -36,9 +36,7 @@ import static extension org.eclipse.xtext.nodemodel.util.NodeModelUtils.*
* @since 2.11
*/
@Singleton
class HoverService {
public static val EMPTY_HOVER = new Hover(emptyList, null)
class HoverService implements IHoverService {
@Inject
extension DocumentExtensions
@ -52,7 +50,7 @@ class HoverService {
@Inject
extension IEObjectDocumentationProvider
def Hover hover(
override Hover hover(
Document document,
XtextResource resource,
TextDocumentPositionParams params,

View file

@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* 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
*******************************************************************************/
package org.eclipse.xtext.ide.server.hover
import org.eclipse.lsp4j.Hover
import org.eclipse.lsp4j.TextDocumentPositionParams
import org.eclipse.xtext.ide.server.Document
import org.eclipse.xtext.resource.XtextResource
import org.eclipse.xtext.util.CancelIndicator
import com.google.inject.ImplementedBy
/**
* @author Sven Efftinge - Initial contribution and API
*/
@ImplementedBy(HoverService)
interface IHoverService {
public static val EMPTY_HOVER = new Hover(emptyList, null)
/**
* callback for 'textDocument/hover' requests.
*/
def Hover hover(Document document, XtextResource resource, TextDocumentPositionParams params, CancelIndicator cancelIndicator);
}

View file

@ -0,0 +1,22 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* 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
*/
package org.eclipse.xtext.ide.server;
import org.eclipse.lsp4j.InitializeParams;
import org.eclipse.lsp4j.ServerCapabilities;
/**
* @author Sven Efftinge - Initial contribution and API
*/
@SuppressWarnings("all")
public interface ICapabilitiesContributor {
/**
* Allows an individual language to contribute to and overwrite properties in the server's capabilities.
*/
public abstract ServerCapabilities contribute(final ServerCapabilities capabilities, final InitializeParams params);
}

View file

@ -27,6 +27,7 @@ import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.lsp4j.CodeActionParams;
import org.eclipse.lsp4j.CodeLens;
import org.eclipse.lsp4j.CodeLensOptions;
import org.eclipse.lsp4j.CodeLensParams;
import org.eclipse.lsp4j.ColoringInformation;
import org.eclipse.lsp4j.ColoringParams;
@ -83,16 +84,19 @@ import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor;
import org.eclipse.xtext.diagnostics.Severity;
import org.eclipse.xtext.ide.server.BuildManager;
import org.eclipse.xtext.ide.server.Document;
import org.eclipse.xtext.ide.server.ICapabilitiesContributor;
import org.eclipse.xtext.ide.server.ILanguageServerAccess;
import org.eclipse.xtext.ide.server.ILanguageServerExtension;
import org.eclipse.xtext.ide.server.UriExtensions;
import org.eclipse.xtext.ide.server.WorkspaceManager;
import org.eclipse.xtext.ide.server.codelens.ICodeLensResolver;
import org.eclipse.xtext.ide.server.codelens.ICodeLensService;
import org.eclipse.xtext.ide.server.coloring.IColoringService;
import org.eclipse.xtext.ide.server.concurrent.RequestManager;
import org.eclipse.xtext.ide.server.contentassist.ContentAssistService;
import org.eclipse.xtext.ide.server.findReferences.WorkspaceResourceAccess;
import org.eclipse.xtext.ide.server.formatting.FormattingService;
import org.eclipse.xtext.ide.server.hover.HoverService;
import org.eclipse.xtext.ide.server.hover.IHoverService;
import org.eclipse.xtext.ide.server.occurrences.IDocumentHighlightService;
import org.eclipse.xtext.ide.server.signatureHelp.ISignatureHelpService;
import org.eclipse.xtext.ide.server.symbol.DocumentSymbolService;
@ -169,6 +173,14 @@ public class LanguageServerImpl implements LanguageServer, WorkspaceService, Tex
this.resourceAccess = _workspaceResourceAccess;
}
private Iterable<? extends IResourceServiceProvider> getAllLanguages() {
final Function1<String, IResourceServiceProvider> _function = (String ext) -> {
final URI synthUri = URI.createURI(("synth:///file." + ext));
return this.languagesRegistry.getResourceServiceProvider(synthUri);
};
return ListExtensions.<String, IResourceServiceProvider>map(IterableExtensions.<String>sort(IterableExtensions.<String>toList(this.languagesRegistry.getExtensionToFactoryMap().keySet())), _function);
}
@Override
public CompletableFuture<InitializeResult> initialize(final InitializeParams params) {
if ((this.params != null)) {
@ -188,22 +200,46 @@ public class LanguageServerImpl implements LanguageServer, WorkspaceService, Tex
it.setReferencesProvider(Boolean.valueOf(true));
it.setDocumentSymbolProvider(Boolean.valueOf(true));
it.setWorkspaceSymbolProvider(Boolean.valueOf(true));
final Function1<IResourceServiceProvider, Boolean> _function_1 = (IResourceServiceProvider it_1) -> {
ICodeLensService _get = it_1.<ICodeLensService>get(ICodeLensService.class);
return Boolean.valueOf((_get != null));
};
boolean _exists = IterableExtensions.exists(this.getAllLanguages(), _function_1);
if (_exists) {
CodeLensOptions _codeLensOptions = new CodeLensOptions();
final Procedure1<CodeLensOptions> _function_2 = (CodeLensOptions it_1) -> {
final Function1<IResourceServiceProvider, Boolean> _function_3 = (IResourceServiceProvider it_2) -> {
ICodeLensResolver _get = it_2.<ICodeLensResolver>get(ICodeLensResolver.class);
return Boolean.valueOf((_get != null));
};
it_1.setResolveProvider(IterableExtensions.exists(this.getAllLanguages(), _function_3));
};
CodeLensOptions _doubleArrow = ObjectExtensions.<CodeLensOptions>operator_doubleArrow(_codeLensOptions, _function_2);
it.setCodeLensProvider(_doubleArrow);
}
SignatureHelpOptions _signatureHelpOptions = new SignatureHelpOptions(Collections.<String>unmodifiableList(CollectionLiterals.<String>newArrayList("(", ",")));
it.setSignatureHelpProvider(_signatureHelpOptions);
it.setTextDocumentSync(TextDocumentSyncKind.Incremental);
CompletionOptions _completionOptions = new CompletionOptions();
final Procedure1<CompletionOptions> _function_1 = (CompletionOptions it_1) -> {
final Procedure1<CompletionOptions> _function_3 = (CompletionOptions it_1) -> {
it_1.setResolveProvider(Boolean.valueOf(false));
it_1.setTriggerCharacters(Collections.<String>unmodifiableList(CollectionLiterals.<String>newArrayList(".")));
};
CompletionOptions _doubleArrow = ObjectExtensions.<CompletionOptions>operator_doubleArrow(_completionOptions, _function_1);
it.setCompletionProvider(_doubleArrow);
CompletionOptions _doubleArrow_1 = ObjectExtensions.<CompletionOptions>operator_doubleArrow(_completionOptions, _function_3);
it.setCompletionProvider(_doubleArrow_1);
it.setDocumentFormattingProvider(Boolean.valueOf(true));
it.setDocumentRangeFormattingProvider(Boolean.valueOf(true));
it.setDocumentHighlightProvider(Boolean.valueOf(true));
};
ServerCapabilities _doubleArrow = ObjectExtensions.<ServerCapabilities>operator_doubleArrow(_serverCapabilities, _function);
result.setCapabilities(_doubleArrow);
ServerCapabilities capabilities = ObjectExtensions.<ServerCapabilities>operator_doubleArrow(_serverCapabilities, _function);
Iterable<? extends IResourceServiceProvider> _allLanguages = this.getAllLanguages();
for (final IResourceServiceProvider language : _allLanguages) {
ICapabilitiesContributor _get = language.<ICapabilitiesContributor>get(ICapabilitiesContributor.class);
if (_get!=null) {
_get.contribute(capabilities, params);
}
}
result.setCapabilities(capabilities);
final Function0<Object> _function_1 = () -> {
final Procedure2<URI, Iterable<Issue>> _function_2 = (URI $0, Iterable<Issue> $1) -> {
this.publishDiagnostics($0, $1);
@ -537,13 +573,13 @@ public class LanguageServerImpl implements LanguageServer, WorkspaceService, Tex
final Function1<CancelIndicator, Hover> _function = (CancelIndicator cancelIndicator) -> {
final URI uri = this._uriExtensions.toUri(params.getTextDocument().getUri());
final IResourceServiceProvider resourceServiceProvider = this.languagesRegistry.getResourceServiceProvider(uri);
HoverService _get = null;
IHoverService _get = null;
if (resourceServiceProvider!=null) {
_get=resourceServiceProvider.<HoverService>get(HoverService.class);
_get=resourceServiceProvider.<IHoverService>get(IHoverService.class);
}
final HoverService hoverService = _get;
final IHoverService hoverService = _get;
if ((hoverService == null)) {
return HoverService.EMPTY_HOVER;
return IHoverService.EMPTY_HOVER;
}
final Function2<Document, XtextResource, Hover> _function_1 = (Document document, XtextResource resource) -> {
return hoverService.hover(document, resource, params, cancelIndicator);
@ -605,14 +641,82 @@ public class LanguageServerImpl implements LanguageServer, WorkspaceService, Tex
throw new UnsupportedOperationException("TODO: auto-generated method stub");
}
private void installURI(final List<? extends CodeLens> codeLenses, final String uri) {
for (final CodeLens lens : codeLenses) {
Object _data = lens.getData();
boolean _tripleNotEquals = (_data != null);
if (_tripleNotEquals) {
lens.setData(CollectionLiterals.<Object>newArrayList(uri, lens.getData()));
} else {
lens.setData(uri);
}
}
}
private URI uninstallURI(final CodeLens lens) {
URI result = null;
Object _data = lens.getData();
if ((_data instanceof String)) {
result = URI.createURI(lens.getData().toString());
lens.setData(null);
} else {
Object _data_1 = lens.getData();
if ((_data_1 instanceof List<?>)) {
Object _data_2 = lens.getData();
final List<?> l = ((List<?>) _data_2);
result = URI.createURI(IterableExtensions.head(l).toString());
lens.setData(l.get(1));
}
}
return result;
}
@Override
public CompletableFuture<List<? extends CodeLens>> codeLens(final CodeLensParams params) {
throw new UnsupportedOperationException("TODO: auto-generated method stub");
final Function1<CancelIndicator, List<? extends CodeLens>> _function = (CancelIndicator cancelIndicator) -> {
final URI uri = this._uriExtensions.toUri(params.getTextDocument().getUri());
final IResourceServiceProvider resourceServiceProvider = this.languagesRegistry.getResourceServiceProvider(uri);
ICodeLensService _get = null;
if (resourceServiceProvider!=null) {
_get=resourceServiceProvider.<ICodeLensService>get(ICodeLensService.class);
}
final ICodeLensService codeLensService = _get;
if ((codeLensService == null)) {
return CollectionLiterals.<CodeLens>emptyList();
}
final Function2<Document, XtextResource, List<? extends CodeLens>> _function_1 = (Document document, XtextResource resource) -> {
final List<? extends CodeLens> result = codeLensService.computeCodeLenses(document, resource, params, cancelIndicator);
this.installURI(result, uri.toString());
return result;
};
return this.workspaceManager.<List<? extends CodeLens>>doRead(uri, _function_1);
};
return this.requestManager.<List<? extends CodeLens>>runRead(_function);
}
@Override
public CompletableFuture<CodeLens> resolveCodeLens(final CodeLens unresolved) {
return CompletableFuture.<CodeLens>completedFuture(unresolved);
final URI uri = this.uninstallURI(unresolved);
if ((uri == null)) {
return CompletableFuture.<CodeLens>completedFuture(unresolved);
}
final Function1<CancelIndicator, CodeLens> _function = (CancelIndicator cancelIndicator) -> {
final IResourceServiceProvider resourceServiceProvider = this.languagesRegistry.getResourceServiceProvider(uri);
ICodeLensResolver _get = null;
if (resourceServiceProvider!=null) {
_get=resourceServiceProvider.<ICodeLensResolver>get(ICodeLensResolver.class);
}
final ICodeLensResolver resolver = _get;
if ((resolver == null)) {
return unresolved;
}
final Function2<Document, XtextResource, CodeLens> _function_1 = (Document document, XtextResource resource) -> {
final CodeLens result = resolver.resolveCodeLens(document, resource, unresolved, cancelIndicator);
return result;
};
return this.workspaceManager.<CodeLens>doRead(uri, _function_1);
};
return this.requestManager.<CodeLens>runRead(_function);
}
@Override

View file

@ -132,7 +132,8 @@ public class WorkspaceManager {
final Provider<Map<String, ResourceDescriptionsData>> _function_1 = () -> {
return this.fullIndex;
};
projectManager.initialize(projectDescription, projectConfig, this.issueAcceptor, this.openedDocumentsContentProvider, _function_1, cancelIndicator);
projectManager.initialize(projectDescription, projectConfig, this.issueAcceptor,
this.openedDocumentsContentProvider, _function_1, cancelIndicator);
this.projectName2ProjectManager.put(projectDescription.getName(), projectManager);
newProjects.add(projectDescription);
}
@ -150,7 +151,8 @@ public class WorkspaceManager {
protected IWorkspaceConfig getWorkspaceConfig() {
if ((this._workspaceConfig == null)) {
final ResponseError error = new ResponseError(ResponseErrorCode.serverNotInitialized, "Workspace has not been initialized yet.", null);
final ResponseError error = new ResponseError(ResponseErrorCode.serverNotInitialized,
"Workspace has not been initialized yet.", null);
throw new ResponseErrorException(error);
}
return this._workspaceConfig;

View file

@ -0,0 +1,24 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* 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
*/
package org.eclipse.xtext.ide.server.codelens;
import org.eclipse.lsp4j.CodeLens;
import org.eclipse.xtext.ide.server.Document;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.util.CancelIndicator;
/**
* @author Sven Efftinge - Initial contribution and API
*/
@SuppressWarnings("all")
public interface ICodeLensResolver {
/**
* Resolve the given code lens.
*/
public abstract CodeLens resolveCodeLens(final Document document, final XtextResource resource, final CodeLens codeLens, final CancelIndicator indicator);
}

View file

@ -0,0 +1,26 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* 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
*/
package org.eclipse.xtext.ide.server.codelens;
import java.util.List;
import org.eclipse.lsp4j.CodeLens;
import org.eclipse.lsp4j.CodeLensParams;
import org.eclipse.xtext.ide.server.Document;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.util.CancelIndicator;
/**
* @author Sven Efftinge - Initial contribution and API
*/
@SuppressWarnings("all")
public interface ICodeLensService {
/**
* compute code lenses for the given context.
*/
public abstract List<? extends CodeLens> computeCodeLenses(final Document document, final XtextResource resource, final CodeLensParams params, final CancelIndicator indicator);
}

View file

@ -21,6 +21,7 @@ import org.eclipse.xtext.documentation.IEObjectDocumentationProvider;
import org.eclipse.xtext.ide.server.Document;
import org.eclipse.xtext.ide.server.DocumentExtensions;
import org.eclipse.xtext.ide.server.hover.HoverContext;
import org.eclipse.xtext.ide.server.hover.IHoverService;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.parser.IParseResult;
@ -40,9 +41,7 @@ import org.eclipse.xtext.xbase.lib.ListExtensions;
*/
@Singleton
@SuppressWarnings("all")
public class HoverService {
public final static Hover EMPTY_HOVER = new Hover(Collections.<Either<String, MarkedString>>emptyList(), null);
public class HoverService implements IHoverService {
@Inject
@Extension
private DocumentExtensions _documentExtensions;
@ -59,6 +58,7 @@ public class HoverService {
@Extension
private IEObjectDocumentationProvider _iEObjectDocumentationProvider;
@Override
public Hover hover(final Document document, final XtextResource resource, final TextDocumentPositionParams params, final CancelIndicator cancelIndicator) {
final int offset = document.getOffSet(params.getPosition());
final HoverContext context = this.createContext(document, resource, offset);
@ -96,15 +96,15 @@ public class HoverService {
protected Hover hover(final HoverContext context) {
if ((context == null)) {
return HoverService.EMPTY_HOVER;
return IHoverService.EMPTY_HOVER;
}
final List<Either<String, MarkedString>> contents = this.getContents(context);
if ((contents == null)) {
return HoverService.EMPTY_HOVER;
return IHoverService.EMPTY_HOVER;
}
final Range range = this.getRange(context);
if ((range == null)) {
return HoverService.EMPTY_HOVER;
return IHoverService.EMPTY_HOVER;
}
return new Hover(contents, range);
}

View file

@ -0,0 +1,33 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* 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
*/
package org.eclipse.xtext.ide.server.hover;
import com.google.inject.ImplementedBy;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.MarkedString;
import org.eclipse.lsp4j.TextDocumentPositionParams;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.xtext.ide.server.Document;
import org.eclipse.xtext.ide.server.hover.HoverService;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.util.CancelIndicator;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
/**
* @author Sven Efftinge - Initial contribution and API
*/
@ImplementedBy(HoverService.class)
@SuppressWarnings("all")
public interface IHoverService {
public final static Hover EMPTY_HOVER = new Hover(CollectionLiterals.<Either<String, MarkedString>>emptyList(), null);
/**
* callback for 'textDocument/hover' requests.
*/
public abstract Hover hover(final Document document, final XtextResource resource, final TextDocumentPositionParams params, final CancelIndicator cancelIndicator);
}

View file

@ -67,6 +67,8 @@ import org.eclipse.xtext.util.Files
import org.eclipse.xtext.util.Modules2
import org.junit.Assert
import org.junit.Before
import org.eclipse.lsp4j.CodeLens
import org.eclipse.lsp4j.CodeLensParams
/**
* @author Sven Efftinge - Initial contribution and API
@ -288,6 +290,32 @@ abstract class AbstractLanguageServerTest implements Endpoint {
protected dispatch def String toExpectation(ColoringInformation it) {
return '''«range.toExpectation» -> [«styles.join(', ')»]''';
}
protected dispatch def String toExpectation(CodeLens it) {
return command.title + " " +range.toExpectation
}
@Accessors static class TestCodeLensConfiguration extends TextDocumentPositionConfiguration {
String expectedCodeLensItems = ''
(List<? extends CodeLens>)=>void assertCodeLenses = null
}
protected def void testCodeLens((TestCodeLensConfiguration)=>void configurator) {
val extension configuration = new TestCodeLensConfiguration
configuration.filePath = 'MyModel.' + fileExtension
configurator.apply(configuration)
val filePath = initializeContext(configuration).uri
val codeLenses = languageServer.codeLens(new CodeLensParams=>[
textDocument = new TextDocumentIdentifier(filePath)
])
val result = codeLenses.get.map[languageServer.resolveCodeLens(it).get].toList
if (configuration.assertCodeLenses !== null) {
configuration.assertCodeLenses.apply(result)
} else {
assertEquals(expectedCodeLensItems, result.toExpectation)
}
}
protected def void testCompletion((TestCompletionConfiguration)=>void configurator) {
val extension configuration = new TestCompletionConfiguration

View file

@ -26,6 +26,8 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import org.eclipse.lsp4j.CodeLens;
import org.eclipse.lsp4j.CodeLensParams;
import org.eclipse.lsp4j.ColoringInformation;
import org.eclipse.lsp4j.ColoringParams;
import org.eclipse.lsp4j.CompletionItem;
@ -83,6 +85,7 @@ import org.eclipse.xtext.testing.ReferenceTestConfiguration;
import org.eclipse.xtext.testing.SignatureHelpConfiguration;
import org.eclipse.xtext.testing.TestCompletionConfiguration;
import org.eclipse.xtext.testing.TextDocumentConfiguration;
import org.eclipse.xtext.testing.TextDocumentPositionConfiguration;
import org.eclipse.xtext.testing.WorkspaceSymbolConfiguraiton;
import org.eclipse.xtext.util.CancelIndicator;
import org.eclipse.xtext.util.Files;
@ -108,6 +111,31 @@ import org.junit.Before;
@FinalFieldsConstructor
@SuppressWarnings("all")
public abstract class AbstractLanguageServerTest implements Endpoint {
@Accessors
public static class TestCodeLensConfiguration extends TextDocumentPositionConfiguration {
private String expectedCodeLensItems = "";
private Procedure1<? super List<? extends CodeLens>> assertCodeLenses = null;
@Pure
public String getExpectedCodeLensItems() {
return this.expectedCodeLensItems;
}
public void setExpectedCodeLensItems(final String expectedCodeLensItems) {
this.expectedCodeLensItems = expectedCodeLensItems;
}
@Pure
public Procedure1<? super List<? extends CodeLens>> getAssertCodeLenses() {
return this.assertCodeLenses;
}
public void setAssertCodeLenses(final Procedure1<? super List<? extends CodeLens>> assertCodeLenses) {
this.assertCodeLenses = assertCodeLenses;
}
}
@Accessors
protected final String fileExtension;
@ -561,6 +589,45 @@ public abstract class AbstractLanguageServerTest implements Endpoint {
return _builder.toString();
}
protected String _toExpectation(final CodeLens it) {
String _title = it.getCommand().getTitle();
String _plus = (_title + " ");
String _expectation = this.toExpectation(it.getRange());
return (_plus + _expectation);
}
protected void testCodeLens(final Procedure1<? super AbstractLanguageServerTest.TestCodeLensConfiguration> configurator) {
try {
@Extension
final AbstractLanguageServerTest.TestCodeLensConfiguration configuration = new AbstractLanguageServerTest.TestCodeLensConfiguration();
configuration.setFilePath(("MyModel." + this.fileExtension));
configurator.apply(configuration);
final String filePath = this.initializeContext(configuration).getUri();
CodeLensParams _codeLensParams = new CodeLensParams();
final Procedure1<CodeLensParams> _function = (CodeLensParams it) -> {
TextDocumentIdentifier _textDocumentIdentifier = new TextDocumentIdentifier(filePath);
it.setTextDocument(_textDocumentIdentifier);
};
CodeLensParams _doubleArrow = ObjectExtensions.<CodeLensParams>operator_doubleArrow(_codeLensParams, _function);
final CompletableFuture<List<? extends CodeLens>> codeLenses = this.languageServer.codeLens(_doubleArrow);
final Function1<CodeLens, CodeLens> _function_1 = (CodeLens it) -> {
try {
return this.languageServer.resolveCodeLens(it).get();
} catch (Throwable _e) {
throw Exceptions.sneakyThrow(_e);
}
};
final List<CodeLens> result = IterableExtensions.<CodeLens>toList(ListExtensions.map(codeLenses.get(), _function_1));
if ((configuration.assertCodeLenses != null)) {
configuration.assertCodeLenses.apply(result);
} else {
this.assertEquals(configuration.expectedCodeLensItems, this.toExpectation(result));
}
} catch (Throwable _e) {
throw Exceptions.sneakyThrow(_e);
}
}
protected void testCompletion(final Procedure1<? super TestCompletionConfiguration> configurator) {
try {
@Extension
@ -944,6 +1011,8 @@ public abstract class AbstractLanguageServerTest implements Endpoint {
return _toExpectation((Void)null);
} else if (it instanceof Map) {
return _toExpectation((Map<Object, Object>)it);
} else if (it instanceof CodeLens) {
return _toExpectation((CodeLens)it);
} else if (it instanceof ColoringInformation) {
return _toExpectation((ColoringInformation)it);
} else if (it instanceof CompletionItem) {