public (string description, LineChr startPosition, LineChr endPosition) GetHoverDescriptionAtPosition(LineChr lineChr)
        {
            var analysis = GetAnalysis(lineChr);

            if (analysis.KeywordToken == null || analysis.IsAfterAnyErrorLine(lineChr))
            {
                return(null, LineChr.Zero, LineChr.Zero);
            }

            var description = conceptQueries.GetFullDescription(analysis.KeywordToken.Value);

            if (string.IsNullOrEmpty(description))
            {
                description = $"No documentation found for '{analysis.KeywordToken.Value}'.";
            }

            var startPosition = TextDocument.GetLineChr(analysis.KeywordToken.PositionInDslScript);

            var endPosition = lineChr;

            if (analysis.NextKeywordToken != null)
            {
                endPosition = TextDocument.GetLineChr(analysis.NextKeywordToken.PositionInDslScript - 1);
            }

            return(description, startPosition, endPosition);
        }
        public override Task <CompletionList> Handle(CompletionParams request, CancellationToken cancellationToken)
        {
            log.LogDebug($"Completion requested at {request.Position.ToLineChr()}.");

            var document = rhetosWorkspace.GetRhetosDocument(request.TextDocument.Uri);

            if (document == null)
            {
                return(Task.FromResult <CompletionList>(null));
            }

            var keywords = document.GetCompletionKeywordsAtPosition(request.Position.ToLineChr());

            var completionItems = keywords
                                  .Select(keyword => new CompletionItem()
            {
                Label = keyword, Kind = CompletionItemKind.Keyword, Detail = conceptQueries.GetFullDescription(keyword)
            })
                                  .ToList();

            var completionList = new CompletionList(completionItems);

            return(Task.FromResult(completionList));
        }