From 66caca99ad0bb34563e733879b013aa239f11b52 Mon Sep 17 00:00:00 2001 From: akosyakov Date: Fri, 3 Jun 2016 11:02:53 +0200 Subject: [PATCH] [lsi][testing] Extracted the reusable language server test infrastructure Change-Id: I848bc2f59b1b636ff3ee666aa1057eb15025a116 Signed-off-by: akosyakov --- .../server/AbstractLanguageServerTest.xtend | 199 +++++++++++++++++- .../ide/tests/server/CompletionTest.xtend | 34 +-- .../ide/tests/server/DefinitionTest.xtend | 29 +-- .../ide/tests/server/DocumentSymbolTest.xtend | 27 +-- .../xtext/ide/tests/server/HoverTest.xtend | 42 +--- .../ide/tests/server/OpenDocumentTest.xtend | 2 +- .../ide/tests/server/ReferenceTest.xtend | 33 +-- .../xtext/ide/tests/server/ServerTest.xtend | 2 +- .../tests/server/WorkspaceSymbolTest.xtend | 37 +--- 9 files changed, 200 insertions(+), 205 deletions(-) diff --git a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/AbstractLanguageServerTest.xtend b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/AbstractLanguageServerTest.xtend index 7255f854d..14c9a1ecf 100644 --- a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/AbstractLanguageServerTest.xtend +++ b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/AbstractLanguageServerTest.xtend @@ -10,13 +10,17 @@ package org.eclipse.xtext.ide.tests.server import com.google.inject.AbstractModule import com.google.inject.Guice import com.google.inject.Inject +import io.typefox.lsapi.CompletionItem import io.typefox.lsapi.Diagnostic +import io.typefox.lsapi.Hover import io.typefox.lsapi.InitializeParamsImpl import io.typefox.lsapi.InitializeResult import io.typefox.lsapi.Location +import io.typefox.lsapi.MarkedString import io.typefox.lsapi.Position import io.typefox.lsapi.PublishDiagnosticsParams import io.typefox.lsapi.Range +import io.typefox.lsapi.ReferenceContextImpl import io.typefox.lsapi.SymbolInformation import java.io.File import java.io.FileWriter @@ -27,45 +31,60 @@ import java.util.List import java.util.Map import java.util.concurrent.CompletableFuture import java.util.function.Consumer +import org.eclipse.xtend.lib.annotations.Accessors +import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor +import org.eclipse.xtext.LanguageInfo import org.eclipse.xtext.ide.server.LanguageServerImpl import org.eclipse.xtext.ide.server.ServerModule import org.eclipse.xtext.ide.server.UriExtensions import org.eclipse.xtext.ide.server.concurrent.RequestManager +import org.eclipse.xtext.resource.IResourceServiceProvider import org.eclipse.xtext.util.CancelIndicator import org.eclipse.xtext.util.Files import org.eclipse.xtext.util.Modules2 import org.junit.Before -import static io.typefox.lsapi.util.LsapiFactories.* +import static org.junit.Assert.* + +import static extension io.typefox.lsapi.util.LsapiFactories.* /** * @author Sven Efftinge - Initial contribution and API */ -class AbstractLanguageServerTest implements Consumer { +@FinalFieldsConstructor +abstract class AbstractLanguageServerTest implements Consumer { + + @Accessors + protected val String fileExtension @Before def void setup() { val module = Modules2.mixin(new ServerModule, new AbstractModule() { - + override protected configure() { bind(RequestManager).toInstance(new RequestManager() { - + override runWrite((CancelIndicator)=>void writeRequest, CancelIndicator cancelIndicator) { writeRequest.apply(cancelIndicator) return CompletableFuture.completedFuture(null) } - + override runRead((CancelIndicator)=>V readRequest, CancelIndicator cancelIndicator) { return CompletableFuture.completedFuture(readRequest.apply(cancelIndicator)) } - + }) } - + }) - + val injector = Guice.createInjector(module) injector.injectMembers(this) + + val resourceServiceProvider = resourceServerProviderRegistry.extensionToFactoryMap.get(fileExtension) + if (resourceServiceProvider instanceof IResourceServiceProvider) + languageInfo = resourceServiceProvider.get(LanguageInfo) + // register notification callbacks languageServer.getTextDocumentService().onPublishDiagnostics(this) @@ -77,11 +96,15 @@ class AbstractLanguageServerTest implements Consumer { root.deleteOnExit } + @Inject + protected IResourceServiceProvider.Registry resourceServerProviderRegistry + @Inject extension UriExtensions @Inject protected LanguageServerImpl languageServer protected Map> diagnostics = newHashMap() protected File root + protected LanguageInfo languageInfo protected def Path getRootPath() { root.toPath().toAbsolutePath().normalize() @@ -103,9 +126,13 @@ class AbstractLanguageServerTest implements Consumer { } protected def void open(String fileUri, String model) { - languageServer.didOpen(newDidOpenTextDocumentParams(fileUri, "testlang", 1, model)) + open(fileUri, languageInfo.languageName, model) } - + + protected def void open(String fileUri, String langaugeId, String model) { + languageServer.didOpen(newDidOpenTextDocumentParams(fileUri, langaugeId, 1, model)) + } + protected def void close(String fileUri) { languageServer.didClose(newDidCloseTextDocumentParams(fileUri)) } @@ -131,7 +158,7 @@ class AbstractLanguageServerTest implements Consumer { «element.toExpectation» «ENDFOR» ''' - + protected def dispatch String toExpectation(Void it) { '' } protected def dispatch String toExpectation(Location it) '''«uri.relativize» «range.toExpectation»''' @@ -150,4 +177,154 @@ class AbstractLanguageServerTest implements Consumer { } ''' + protected def dispatch String toExpectation(CompletionItem it) ''' + «label»«IF !detail.nullOrEmpty» («detail»)«ENDIF»«IF insertText != label» -> «insertText»«ENDIF» + ''' + + protected dispatch def String toExpectation(Hover it) ''' + «range.toExpectation» + «FOR content : contents» + «content.toExpectation» + «ENDFOR» + ''' + + protected dispatch def String toExpectation( + MarkedString it + ) '''«IF !language.nullOrEmpty»«language» -> «ENDIF»«value»''' + + protected def void testCompletion((TestCompletionConfiguration)=>void configurator) { + val extension configuration = new TestCompletionConfiguration + configuration.filePath = 'MyModel.' + fileExtension + configurator.apply(configuration) + + val fileUri = filePath -> model + + initialize + open(fileUri, model) + + val completionItems = languageServer.completion(newTextDocumentPositionParams(fileUri, line, column)) + + val actualCompletionItems = completionItems.get.items.toExpectation + assertEquals(expectedCompletionItems, actualCompletionItems) + } + + protected def void testDefinition((DefinitionTestConfiguration)=>void configurator) { + val extension configuration = new DefinitionTestConfiguration + configuration.filePath = 'MyModel.' + fileExtension + configurator.apply(configuration) + + val fileUri = filePath -> model + + initialize + open(fileUri, model) + + val definitions = languageServer.definition(newTextDocumentPositionParams(fileUri, line, column)) + val actualDefinitions = definitions.get.toExpectation + assertEquals(expectedDefinitions, actualDefinitions) + } + + protected def void testHover((HoverTestConfiguration)=>void configurator) { + val extension configuration = new HoverTestConfiguration + configuration.filePath = 'MyModel.' + fileExtension + configurator.apply(configuration) + + val fileUri = filePath -> model + + initialize + open(fileUri, model) + + val hover = languageServer.hover(newTextDocumentPositionParams(fileUri, line, column)) + val actualHover = hover.get.toExpectation + assertEquals(expectedHover, actualHover) + } + + protected def void testDocumentSymbol((DocumentSymbolConfiguraiton)=>void configurator) { + val extension configuration = new DocumentSymbolConfiguraiton + configuration.filePath = 'MyModel.' + fileExtension + configurator.apply(configuration) + val fileUri = filePath -> model + + initialize + open(fileUri, model) + + val symbols = languageServer.documentSymbol(fileUri.newDocumentSymbolParams) + val String actualSymbols = symbols.get.toExpectation + assertEquals(expectedSymbols, actualSymbols) + } + + protected def void testSymbol((WorkspaceSymbolConfiguraiton)=>void configurator) { + val extension configuration = new WorkspaceSymbolConfiguraiton + configuration.filePath = 'MyModel.' + fileExtension + configurator.apply(configuration) + val fileUri = filePath -> model + + initialize + open(fileUri, model) + + val symbols = languageServer.symbol(query.newWorkspaceSymbolParams).get + val String actualSymbols = symbols.toExpectation + assertEquals(expectedSymbols, actualSymbols) + } + + protected def void testReferences((ReferenceTestConfiguration)=>void configurator) { + val extension configuration = new ReferenceTestConfiguration + configuration.filePath = 'MyModel.' + fileExtension + configurator.apply(configuration) + + val fileUri = filePath -> model + + initialize + open(fileUri, model) + + val referenceContext = new ReferenceContextImpl + referenceContext.includeDeclaration = includeDeclaration + val definitions = languageServer.references(newReferenceParams(fileUri, line, column, referenceContext)) + val actualDefinitions = definitions.get.toExpectation + assertEquals(expectedReferences, actualDefinitions) + } + +} + +@Accessors +class TestCompletionConfiguration extends TextDocumentPositionConfiguration { + String expectedCompletionItems = '' +} + +@Accessors +class DefinitionTestConfiguration extends TextDocumentPositionConfiguration { + String expectedDefinitions = '' +} + +@Accessors +class HoverTestConfiguration extends TextDocumentPositionConfiguration { + String expectedHover = '' +} + +@Accessors +class DocumentSymbolConfiguraiton extends TextDocumentConfiguration { + String expectedSymbols = '' +} + +@Accessors +class ReferenceTestConfiguration extends TextDocumentPositionConfiguration { + boolean includeDeclaration = false + String expectedReferences = '' +} + +@Accessors +class WorkspaceSymbolConfiguraiton extends TextDocumentConfiguration { + String query = '' + String expectedSymbols = '' +} + +@Accessors +class TextDocumentPositionConfiguration extends TextDocumentConfiguration { + int line = 0 + int column = 0 +} + +@Accessors +class TextDocumentConfiguration { + String model = '' + String filePath } diff --git a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/CompletionTest.xtend b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/CompletionTest.xtend index 556affc16..bd95a19ec 100644 --- a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/CompletionTest.xtend +++ b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/CompletionTest.xtend @@ -7,17 +7,12 @@ *******************************************************************************/ package org.eclipse.xtext.ide.tests.server -import io.typefox.lsapi.CompletionItem -import org.eclipse.xtend.lib.annotations.Accessors import org.junit.Test -import static io.typefox.lsapi.util.LsapiFactories.* -import static org.junit.Assert.* - /** * @author kosyakov - Initial contribution and API */ -class CompletionTest extends AbstractLanguageServerTest { +class CompletionTest extends AbstractTestLangLanguageServerTest { @Test def void testCompletion_01() { @@ -60,31 +55,4 @@ class CompletionTest extends AbstractLanguageServerTest { ] } - protected def testCompletion((TestCompletionConfiguration)=>void configurator) { - val extension configuration = new TestCompletionConfiguration - configurator.apply(configuration) - val fileUri = filePath -> model - - initialize - open(fileUri, model) - - val completionItems = languageServer.completion(newTextDocumentPositionParams(fileUri, line, column)) - - val actualCompletionItems = completionItems.get.items.toExpectation - assertEquals(expectedCompletionItems, actualCompletionItems) - } - - protected def dispatch String toExpectation(CompletionItem it) ''' - «label»«IF !detail.nullOrEmpty» («detail»)«ENDIF»«IF insertText != label» -> «insertText»«ENDIF» - ''' - - @Accessors - static class TestCompletionConfiguration { - String model = '' - String filePath = 'MyModel.testlang' - int line = 0 - int column = 0 - String expectedCompletionItems = '' - } - } diff --git a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/DefinitionTest.xtend b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/DefinitionTest.xtend index f484414dd..a80df3fee 100644 --- a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/DefinitionTest.xtend +++ b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/DefinitionTest.xtend @@ -7,16 +7,12 @@ *******************************************************************************/ package org.eclipse.xtext.ide.tests.server -import org.eclipse.xtend.lib.annotations.Accessors import org.junit.Test -import static org.junit.Assert.* -import static io.typefox.lsapi.util.LsapiFactories.* - /** * @author kosyakov - Initial contribution and API */ -class DefinitionTest extends AbstractLanguageServerTest { +class DefinitionTest extends AbstractTestLangLanguageServerTest { @Test def void testDefinition_01() { @@ -35,27 +31,4 @@ class DefinitionTest extends AbstractLanguageServerTest { ] } - protected def void testDefinition((DefinitionTestConfiguration)=>void configurator) { - val extension configuration = new DefinitionTestConfiguration - configurator.apply(configuration) - - val fileUri = filePath -> model - - initialize - open(fileUri, model) - - val definitions = languageServer.definition(newTextDocumentPositionParams(fileUri, line, column)) - val actualDefinitions = definitions.get.toExpectation - assertEquals(expectedDefinitions, actualDefinitions) - } - - @Accessors - static class DefinitionTestConfiguration { - String model = '' - String filePath = 'MyModel.testlang' - int line = 0 - int column = 0 - String expectedDefinitions = '' - } - } diff --git a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/DocumentSymbolTest.xtend b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/DocumentSymbolTest.xtend index d671fd011..026f69d2b 100644 --- a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/DocumentSymbolTest.xtend +++ b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/DocumentSymbolTest.xtend @@ -7,17 +7,12 @@ *******************************************************************************/ package org.eclipse.xtext.ide.tests.server -import org.eclipse.xtend.lib.annotations.Accessors import org.junit.Test -import static org.junit.Assert.* - -import static extension io.typefox.lsapi.util.LsapiFactories.* - /** * @author kosyakov - Initial contribution and API */ -class DocumentSymbolTest extends AbstractLanguageServerTest { +class DocumentSymbolTest extends AbstractTestLangLanguageServerTest { @Test def void testDocumentSymbol_01() { @@ -58,24 +53,4 @@ class DocumentSymbolTest extends AbstractLanguageServerTest { ] } - protected def void testDocumentSymbol((DocumentSymbolConfiguraiton)=>void configurator) { - val extension configuration = new DocumentSymbolConfiguraiton - configurator.apply(configuration) - val fileUri = filePath -> model - - initialize - open(fileUri, model) - - val symbols = languageServer.documentSymbol(fileUri.newDocumentSymbolParams) - val String actualSymbols = symbols.get.toExpectation - assertEquals(expectedSymbols, actualSymbols) - } - - @Accessors - static class DocumentSymbolConfiguraiton { - String model = '' - String filePath = 'MyModel.testlang' - String expectedSymbols = '' - } - } diff --git a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/HoverTest.xtend b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/HoverTest.xtend index b7757e3ac..d1645998b 100644 --- a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/HoverTest.xtend +++ b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/HoverTest.xtend @@ -7,18 +7,12 @@ *******************************************************************************/ package org.eclipse.xtext.ide.tests.server -import io.typefox.lsapi.Hover -import io.typefox.lsapi.MarkedString -import org.eclipse.xtend.lib.annotations.Accessors import org.junit.Test -import static io.typefox.lsapi.util.LsapiFactories.* -import static org.junit.Assert.* - /** * @author kosyakov - Initial contribution and API */ -class HoverTest extends AbstractLanguageServerTest { +class HoverTest extends AbstractTestLangLanguageServerTest { @Test def void testHover_01() { @@ -73,38 +67,4 @@ class HoverTest extends AbstractLanguageServerTest { ] } - protected def void testHover((HoverTestConfiguration)=>void configurator) { - val extension configuration = new HoverTestConfiguration - configurator.apply(configuration) - - val fileUri = filePath -> model - - initialize - open(fileUri, model) - - val hover = languageServer.hover(newTextDocumentPositionParams(fileUri, line, column)) - val actualHover = hover.get.toExpectation - assertEquals(expectedHover, actualHover) - } - - @Accessors - static class HoverTestConfiguration { - String model = '' - String filePath = 'MyModel.testlang' - int line = 0 - int column = 0 - String expectedHover = '' - } - - protected dispatch def String toExpectation(Hover it) ''' - «range.toExpectation» - «FOR content : contents» - «content.toExpectation» - «ENDFOR» - ''' - - protected dispatch def String toExpectation( - MarkedString it - ) '''«IF !language.nullOrEmpty»«language» -> «ENDIF»«value»''' - } diff --git a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/OpenDocumentTest.xtend b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/OpenDocumentTest.xtend index 0894aafc1..bebb929ca 100644 --- a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/OpenDocumentTest.xtend +++ b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/OpenDocumentTest.xtend @@ -17,7 +17,7 @@ import static extension io.typefox.lsapi.util.LsapiFactories.* /** * @author Sven Efftinge - Initial contribution and API */ -class OpenDocumentTest extends AbstractLanguageServerTest { +class OpenDocumentTest extends AbstractTestLangLanguageServerTest { @Test def void testOpenedDocumentShadowsPersistedFile() { diff --git a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/ReferenceTest.xtend b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/ReferenceTest.xtend index 559af5d02..7fa442367 100644 --- a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/ReferenceTest.xtend +++ b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/ReferenceTest.xtend @@ -7,17 +7,12 @@ *******************************************************************************/ package org.eclipse.xtext.ide.tests.server -import io.typefox.lsapi.ReferenceContextImpl -import org.eclipse.xtend.lib.annotations.Accessors import org.junit.Test -import static io.typefox.lsapi.util.LsapiFactories.* -import static org.junit.Assert.* - /** * @author kosyakov - Initial contribution and API */ -class ReferenceTest extends AbstractLanguageServerTest { +class ReferenceTest extends AbstractTestLangLanguageServerTest { @Test def void testReferences_01() { @@ -53,30 +48,4 @@ class ReferenceTest extends AbstractLanguageServerTest { ] } - protected def void testReferences((ReferenceTestConfiguration)=>void configurator) { - val extension configuration = new ReferenceTestConfiguration - configurator.apply(configuration) - - val fileUri = filePath -> model - - initialize - open(fileUri, model) - - val referenceContext = new ReferenceContextImpl - referenceContext.includeDeclaration = includeDeclaration - val definitions = languageServer.references(newReferenceParams(fileUri, line, column, referenceContext)) - val actualDefinitions = definitions.get.toExpectation - assertEquals(expectedReferences, actualDefinitions) - } - - @Accessors - static class ReferenceTestConfiguration { - String model = '' - String filePath = 'MyModel.testlang' - int line = 0 - int column = 0 - boolean includeDeclaration = false - String expectedReferences = '' - } - } diff --git a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/ServerTest.xtend b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/ServerTest.xtend index 6fa8acd79..187aa3c7f 100644 --- a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/ServerTest.xtend +++ b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/ServerTest.xtend @@ -17,7 +17,7 @@ import static extension io.typefox.lsapi.util.LsapiFactories.* /** * @author Sven Efftinge - Initial contribution and API */ -class ServerTest extends AbstractLanguageServerTest { +class ServerTest extends AbstractTestLangLanguageServerTest { @Test def void testInitializeBuild() { diff --git a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/WorkspaceSymbolTest.xtend b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/WorkspaceSymbolTest.xtend index f8b22d4a5..ce47fa3f0 100644 --- a/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/WorkspaceSymbolTest.xtend +++ b/tests/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server/WorkspaceSymbolTest.xtend @@ -7,21 +7,16 @@ *******************************************************************************/ package org.eclipse.xtext.ide.tests.server -import org.eclipse.xtend.lib.annotations.Accessors import org.junit.Test -import static org.junit.Assert.* - -import static extension io.typefox.lsapi.util.LsapiFactories.* - /** * @author kosyakov - Initial contribution and API */ -class WorkspaceSymbolTest extends AbstractLanguageServerTest { +class WorkspaceSymbolTest extends AbstractTestLangLanguageServerTest { @Test - def void testDocumentSymbol_01() { - testDocumentSymbol[ + def void testSymbol_01() { + testSymbol[ model = ''' type Foo { int bar @@ -53,8 +48,8 @@ class WorkspaceSymbolTest extends AbstractLanguageServerTest { } @Test - def void testDocumentSymbol_02() { - testDocumentSymbol[ + def void testSymbol_02() { + testSymbol[ model = ''' type Foo { int bar @@ -84,27 +79,5 @@ class WorkspaceSymbolTest extends AbstractLanguageServerTest { ''' ] } - - protected def void testDocumentSymbol((WorkspaceSymbolConfiguraiton)=>void configurator) { - val extension configuration = new WorkspaceSymbolConfiguraiton - configurator.apply(configuration) - val fileUri = filePath -> model - - initialize - open(fileUri, model) - - val symbols = languageServer.symbol(query.newWorkspaceSymbolParams).get - - val String actualSymbols = symbols.toExpectation - assertEquals(expectedSymbols, actualSymbols) - } - - @Accessors - static class WorkspaceSymbolConfiguraiton { - String model = '' - String filePath = 'MyModel.testlang' - String query = '' - String expectedSymbols = '' - } } \ No newline at end of file