mirror of
https://github.com/sigmasternchen/xtext-core
synced 2025-03-15 16:28:56 +00:00
Merge pull request #395 from eclipse/se_codelens
[lsp] added hooks for code lenses and language specific capabalities
This commit is contained in:
commit
3627b52a6b
22 changed files with 879 additions and 193 deletions
|
@ -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)
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue