blob: 44f066fa69e3dbac1a834ac9a76ef47482f067d4 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Xtext - LSP Support</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description"
content="The website of Eclipse Xtext, an open-source framework for development of programming languages and domain-specific languages">
<meta name="author" content="Sven Efftinge">
<meta name="author" content="Miro Spoenemann">
<!-- styles -->
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<!-- Le fav and touch icons -->
<link rel="shortcut icon" href="/Xtext/images/favicon.png">
<link href="/Xtext/css/bootstrap.css" rel="stylesheet" type='text/css'>
<link href="/Xtext/css/bootstrap-responsive.css" rel="stylesheet" type='text/css'>
<link href="/Xtext/css/shield-responsive.css" rel="stylesheet" type='text/css'>
<link href='/Xtext/css/fonts.css' rel='stylesheet' type='text/css'>
<link href="/Xtext/css/prettyPhoto.css" rel="stylesheet" media="screen" type='text/css'>
<link href="/Xtext/css/prettify.css" type="text/css" rel="stylesheet"/>
<link href="/Xtext/css/style.css" rel="stylesheet" type='text/css'>
<!-- cover flow -->
<link href="/Xtext/css/coverflow.css" rel="stylesheet" type='text/css'>
<!--[if lt IE 9]>
<link href="/css/iebugs.css" rel="stylesheet" type='text/css'>
<![endif]-->
<!-- BEGIN Cookie Consent
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.css" />
<script src="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.js"></script>
<script>
window.addEventListener("load", function(){
window.cookieconsent.initialise({
"palette": {
"popup": {
"background": "#000"
},
"button": {
"background": "#f1d600"
}
},
"theme": "edgeless",
"type": "opt-in",
onInitialise: function (status) {
var type = this.options.type;
var didConsent = this.hasConsented();
if (type == 'opt-in' && didConsent) {
// TODO: enable cookies
}
if (type == 'opt-out' && !didConsent) {
// TODO: disable cookies
}
},
onStatusChange: function(status, chosenBefore) {
var type = this.options.type;
var didConsent = this.hasConsented();
if (type == 'opt-in' && didConsent) {
// TODO: enable cookies
}
if (type == 'opt-out' && !didConsent) {
// TODO: disable cookies
}
},
onRevokeChoice: function() {
var type = this.options.type;
if (type == 'opt-in') {
// TODO: disable cookies
}
if (type == 'opt-out') {
// TODO: enable cookies
}
},
"content": {
"href": "http://www.eclipse.org/legal/privacy.php"
}
})});
</script>
END Cookie Consent -->
</head>
<body>
<header class="site-header">
<!-- Navbar -->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse"
data-target=".nav-collapse"> <span class="icon-bar"></span> <span
class="icon-bar"></span> <span class="icon-bar"></span>
</a> <a class="brand" href="/Xtext/index.html"></a>
<div class="nav-collapse collapse" style="height: 0px;">
<ul class="nav">
<!--li ><a href="/Xtext/news.html">News</a></li-->
<li ><a href="/Xtext/download.html">Download</a></li>
<li ><a href="/Xtext/documentation/index.html">Documentation</a></li>
<li ><a href="/Xtext/community.html">Community</a></li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Support &amp; Trainings<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="https://www.itemis.com/en/xtext/support-and-team/" target="_blank">itemis</a></li>
<li><a href="https://www.typefox.io/language-engineering/" target="_blank">TypeFox</a></li>
</ul>
</li>
<li ><a href="http://xtend-lang.org">Xtend</a></li>
</ul>
<!--div class="nav pull-right">
<li ><a><iframe src="https://ghbtns.com/github-btn.html?user=eclipse&repo=xtext&type=star&count=true" frameborder="0" scrolling="0" width="170px" height="20px"></iframe></a></li>
</div-->
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>
<!-- Navbar End -->
</header>
<div class="page-content">
<script>
function startSearch(event) {
if (event.keyCode == 13) {
var q = 'site:eclipse.org/Xtext/documentation+' + event.target.value;
window.open('https://www.google.com/search?q=' + q, "_self");
}
}
</script>
<div class="wrapper">
<div id="page">
<div class="inner">
<div id="maincontainer" class="container">
<span class="edit-on-github pull-right">
<a href="https://github.com/eclipse/xtext/edit/website-published/xtext-website/documentation/340_lsp_support.md">Edit on Github</a>
</span>
<div class="span3" style="margin-left: 0px;">
<div class="search-bar">
<img src="/Xtext/images/search-gray.png"/>
<input type="search" id="google-search" onkeyup="startSearch(event);"/>
</div>
<ul id="nav-outline" style="margin-left: 0px;">
<li class="nav-part">Getting Started</li>
<li><a href="102_domainmodelwalkthrough.html">15 Minutes Tutorial</a></li>
<li><a href="103_domainmodelnextsteps.html">15 Minutes Tutorial - Extended</a></li>
<li><a href="104_jvmdomainmodel.html">Five simple steps to your JVM language</a></li>
<li class="nav-part">Reference Documentation</li>
<li><a href="301_grammarlanguage.html">The Grammar Language</a></li>
<li><a href="302_configuration.html">Configuration</a></li>
<li><a href="303_runtime_concepts.html">Language Implementation</a></li>
<li><a href="305_xbase.html">Integration with Java</a></li>
<li><a href="307_special_languages.html">Typical Language Configurations</a></li>
<li><a href="308_emf_integration.html">Integration with EMF</a></li>
<li><a href="310_eclipse_support.html">Eclipse Support</a></li>
<li><a href="330_web_support.html">Web Editor Support</a></li>
<li><a href="340_lsp_support.html">LSP Support</a></li>
<li><a href="350_continuous_integration.html">Continuous Integration</a></li>
</ul>
</div>
<div class="span8 doc-contents">
<h1 id="lsp-support">LSP Support</h1>
<p>Xtext supports the generation of language servers that comply to the <a href="https://microsoft.github.io/language-server-protocol/">Language Server Protocol (LSP)</a>.</p>
<h2 id="getting-started-eclipse">Getting Started in Eclipse</h2>
<p><strong>Step 1:</strong> Create a new Xtext Project with language server support and Maven as the preferred build system.<br />
<img src="images/LSP_01_XtextWizardMaven.png" alt="Xtext project wizard" /></p>
<p><strong>Step 2:</strong> Implement the Domainmodel language following the <a href="https://www.eclipse.org/Xtext/documentation/102_domainmodelwalkthrough.html">Xtext - 15 Minutes Tutorial</a>.</p>
<p><strong>Step 3:</strong> Try out the Domainmodel language server in Eclipse based on <a href="https://projects.eclipse.org/projects/technology.lsp4e">LSP4E</a>.</p>
<ol>
<li>
<p>Configure a content type to the <code>*.dmodel</code> files:<br />
<img src="images/LSP_02_DomainmodelContentType.png" alt="Domainmodel Content Type" /></p>
</li>
<li>
<p>Create a launch configuration that starts the Domainmodel language server:<br />
<img src="images/LSP_03_DomainmodelLanguageServerLauncher.png" alt="Domainmodel Language Server Launcher" /></p>
</li>
<li>
<p>Assign the Domainmodel content type to the Domainmodel language server launcher:<br />
<img src="images/LSP_04_DomainmodelLanguageServer.png" alt="Domainmodel Language Server" /></p>
</li>
<li>LSP does not support syntax highlighting (usually it is done on the client side). The following <a href="https://projects.eclipse.org/projects/technology.tm4e">TextMate</a> json file adds syntax highlighting support for the keywords, single-line and multi-line comments of the Domainmodel language:
<pre><code class="language-json">{
"name": "Domainmodel",
"scopeName": "text.dmodel",
"fileTypes": [
"dmodel"
],
"repository": {
"general": {
"patterns": [
{
"include": "#linecomment"
},
{
"include": "#blockcomment"
},
{
"include": "#keyword"
}
]
},
"linecomment": {
"name": "comment.line.double-dash.dmodel",
"begin": "(^[ \\t]+)?(?=//)",
"end": "(?=$)"
},
"blockcomment": {
"name": "comment.block.dmodel",
"begin": "/\\*(\\*)?(?!/)",
"end": "\\*/"
},
"keyword": {
"name": "keyword.control.mydsl",
"match": "\\b(entity|datatype)\\b|!"
}
},
"patterns": [
{
"include": "#general"
}
],
"uuid": "8383e49a-fa0d-4bb5-827b-10e8abb294ca"
}
</code></pre>
</li>
<li>Open a <code>*.dmodel</code> file with the Generic Editor and explore the supported language features like syntax highlighting, content assist, validation, displaying code lenses, quickfixes, formatting, … :<br />
<img src="images/LSP_05_DomainmodelLanguageFeatures.png" alt="Domainmodel Language Features" /></li>
</ol>
<h2 id="getting-started-intellij">Getting Started in IntelliJ IDEA</h2>
<p><strong>Step 1:</strong> Create a new Xtext Project with language server support and Gradle as the preferred build system.<br />
<img src="images/LSP_06_XtextWizardGradle.png" alt="Xtext project wizard" /></p>
<p><strong>Step 2:</strong> Implement the Domainmodel language following the <a href="https://www.eclipse.org/Xtext/documentation/102_domainmodelwalkthrough.html">Xtext - 15 Minutes Tutorial</a>.</p>
<p><strong>Step 3:</strong> Try out the Domainmodel language server in IntelliJ IDEA based on the <a href="https://github.com/gtache/intellij-lsp">gtache LSP plugin</a>.</p>
<ol>
<li>Generate the Language Server jar file using the <code>gradle clean build</code> command. After the gradle build has been completed successfully, the generated jar file is located in the build folder of the ide project:
<pre><code>org.example.domainmodel.ide\build\libs\org.example.domainmodel.ide-1.0.0-SNAPSHOT-ls.jar
</code></pre>
</li>
<li>
<p>Start IntelliJ IDEA and install the LSP plugin via <code>File - Settings... - Plugins - search for 'IntelliJ LSP Support'</code>:<br />
<img src="images/LSP_07_IntelliJLSPPlugin.png" alt="IntelliJ LSP Plugin" /></p>
</li>
<li>
<p>Assign the Domainmodel language server to the <code>*.dmodel</code> extension via <code>File - Settings... - Languages and Frameworks - Language Server Protocol - Server Definitions</code>:<br />
<img src="images/LSP_08_IntelliJLanguageServerDefinition.png" alt="IntelliJ Language Server Definition" /></p>
</li>
<li>
<p>While opening a Domainmodel file for the first time, the <code>*.dmodel</code> file pattern should be configured to be treated as text files and auto-detect the file type by content:<br />
<img src="images/LSP_09_IntelliJFileTypeConfiguration.png" alt="IntelliJ File Type Configuration.png" /></p>
</li>
<li>After that, whenever a <code>*.dmodel</code> file is opened in IntelliJ IDEA, the Domainmodel Language Server is activated (indicated by the green circle at the bottom right) and provides the supported language features (e.g. code completion) to the user:<br />
<img src="images/LSP_10_IntelliJCodeCompletion.png" alt="IntelliJ Code Completion" /></li>
</ol>
<h2 id="further-lsp-clients">Further LSP Clients</h2>
<p>Feel free to implement further LSP clients to the Domainmodel language server based on Atom, Eclipse Che, Eclipse Theia, Monaco Editor, VS Code, … The currenly supported LSP clients are available in the <code>LSP clients</code> section of <a href="https://langserver.org/">https://langserver.org/</a>.</p>
<h2 id="language-features">Language Features</h2>
<p>Currently, Xtext supports the following LSP language features:</p>
<table class="table table-bordered">
<thead>
<tr>
<th><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#version_3_16_0"> LSP 3.16.0 </a> (released on 2020-12-14) <br /> <a href="https://github.com/eclipse/lsp4j/blob/master/CHANGELOG.md#v0100-nov-2020"> LSP4J 0.10.0 </a>(released on 2020-11-05)</th>
<th><a href="https://www.eclipse.org/Xtext/releasenotes.html#/releasenotes/2020/12/01/version-2-24-0"> Xtext 2.24.0 </a> <br /> (released on 2020-12-01)</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#diagnostic">Diagnostic</a> (aka Validation)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion">Completion</a> (aka Content Assist)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#snippet_syntax">Snippets</a> (aka Template Proposals)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover">Hover</a></td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp">Signature Help</a></td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_declaration">Goto Declaration</a> (aka Hyperlinking)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition">Goto Definition</a> (aka Hyperlinking)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_typeDefinition">Goto Type Defintion</a> (aka Hyperlinking)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_implementation">Goto Implementation</a> (aka Hyperlinking)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references">Find References</a></td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight">Document Highlight</a> (aka Marking Occurrences)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol">Document Symbols</a> (aka Model Elements, Outline View)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction">Code Action</a> (aka QuickAssist, QuickFixes)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeLens">Code Lens</a> (aka Code Mining)</td>
<td><div class="not-supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentLink">Document Link</a> (aka Hyperlinking)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentColor">Document Color</a></td>
<td><div class="not-supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting">Document Formatting</a> (aka Formatting)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting">Document Range Formatting</a> (aka Formatting)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_onTypeFormatting">Document on Type Formatting</a> (aka Auto Editing)</td>
<td><div class="not-supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename">Rename</a> (aka Rename Refactoring)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_foldingRange">Folding Range</a> (aka Folding)</td>
<td><div class="not-supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_selectionRange">Selection Range</a> (aka Double Click Text Selection)</td>
<td><div class="not-supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_prepareCallHierarchy">Call Hierarchy</a> </td>
<td><div class="not-supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_semanticTokens">Semantic Tokens</a> (aka Semantic Highlighting)</td>
<td><div class="supported"></div></td>
</tr>
<tr>
<td><a href="https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_linkedEditingRange">Linked Editing Range</a> (aka Rename Refactoring)</td>
<td><div class="supported"></div></td>
</tr>
</tbody>
</table>
<h2 id="unit-testing">Unit Testing</h2>
<p>Automated tests are crucial for the maintainability and the quality of a software product. That is why it is strongly recommended to write unit tests for your language server, too. Xtext provides the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.testing/src/org/eclipse/xtext/testing/AbstractLanguageServerTest.xtend">org.eclipse.xtext.testing.AbstractLanguageServerTest</a> base class that comes in handy when implementing automated LSP unit tests. The <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.ide.tests/src/org/eclipse/xtext/ide/tests/server">org.eclipse.xtext.ide.tests.server</a> package contains JUnit test cases for almost all supported <a href="#language-features">language features</a>. Feel free to study them to get some inspirations on how to implement automated unit tests for your Xtext-based language server.</p>
<p><strong><a href="350_continuous_integration.html">Next Chapter: Continuous Integration</a></strong></p>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="site-footer">
<div id="extra">
<div class="inner">
<div class="container">
<div class="row">
<div class="span6">
<h3 class="footer-links-header">Quick Links</h3>
<ul class="footer-links clearfix">
<li><a href="http://www.eclipse.org/legal/privacy.php">Privacy Policy</a></li>
<li><a href="http://www.eclipse.org/legal/termsofuse.php">Terms of Use</a></li>
<li><a href="http://www.eclipse.org/legal/copyright.php">Copyright Agent</a></li>
<li><a href="http://www.eclipse.org/legal/">Legal</a></li>
</ul>
<ul class="footer-links clearfix">
<li><a href="http://www.eclipse.org">Eclipse Home</a></li>
<li><a href="http://marketplace.eclipse.org/">Market Place</a></li>
<li><a href="http://www.planeteclipse.org/">Eclipse Planet</a></li>
<li><a href="https://www.eclipse.org/forums/index.php/f/27/">Xtext Forum</a></li>
</ul>
</div>
<div class="span6">
<!-- Social Media Links -->
<h3 class="footer-links-header"">Social Media</h3>
<ul class="footer-links clearfix">
<li>
<a href="https://twitter.com/xtext"><img src="/Xtext/images/Twitter-bird-darkgray.png" class="img-responsive" style="margin-right: 5px;height: 1em;" alt="Twitter icon">@xtext on Twitter</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<a href="#" class="scrollup fadeOutRight animated" style="display: none;">ScrollUp</a>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="/Xtext/js/jquery-1.11.3.min.js"></script>
<script src="/Xtext/js/bootstrap.min.js"></script>
<script src="/Xtext/js/jquery.easing.1.3.js" type="text/javascript"></script>
<script src="/Xtext/js/jquery.prettyPhoto.js" type="text/javascript"></script>
<script src="/Xtext/js/prettify.js" type="text/javascript"></script>
<script src="/Xtext/js/lang-xtend.js" type="text/javascript"></script>
<script src="/Xtext/js/lang-common.js" type="text/javascript"></script>
<script src="/Xtext/js/custom.js" type="text/javascript"></script>
<!--script src="https://apis.google.com/js/platform.js" async defer></script-->
<!--script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push([ '_setAccount', 'UA-2429174-3' ]);
_gaq.push([ '_trackPageview' ]);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl'
: 'http://www')
+ '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script-->
<script src="/Xtext/js/coverflow.min.js" type="text/javascript"></script>
<script>
$(function() {
$('#coverflow').coverflow({
active : 1,
visibleAside: 2,
overlap : 0.5,
scale : 0.9,
angle : 20,
trigger : {
"itemfocus" : true,
"swipe" : true,
"mousewheel" : false
}
});
$('#coverflow :hidden').toggle();
$(window).resize(function() {
$('#coverflow').coverflow();
});
});
</script>
</footer>
</body>
</html>