All Downloads are FREE. Search and download functionalities are using the official Maven repository.

es.iti.wakamiti.lsp.internal.CompletionHelper Maven / Gradle / Ivy

/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

package es.iti.wakamiti.lsp.internal;

import static java.util.stream.Collectors.toList;

import java.util.List;
import java.util.regex.*;

import org.eclipse.lsp4j.*;
import org.slf4j.Logger;

public class CompletionHelper {

	private final GherkinDocumentAssessor assessor;
	private final Logger logger;


	public CompletionHelper(GherkinDocumentAssessor assessor, Logger logger) {
		this.assessor = assessor;
		this.logger = logger;
	}


	public List collectCompletions(int lineNumber, int rowPosition) {
		var textDocument = assessor.documentMap.document();
        return collectCompletions(
            lineNumber,
            textDocument.extractRange(TextRange.of(lineNumber,0,lineNumber,rowPosition))
        );
    }


	private List collectCompletions(int lineNumber, String lineContent) {
		String strippedLine = lineContent.stripLeading();
		if (strippedLine.startsWith("#") && !strippedLine.contains(":")) {
			return completeConfigurationProperties(lineContent);
		} else if (assessor.documentMap.isStep(lineNumber, strippedLine)) {
			return completeSteps(strippedLine);
		} else {
			return completeKeywords(lineNumber, strippedLine);
		}
    }


	private List completeConfigurationProperties(String lineContent) {
        String line = lineContent.strip().replace("#","").strip();
        return assessor.hinter.getAvailableProperties()
            .stream()
            .filter(property -> property.startsWith(line))
            .map(this::completionProperty)
            .collect(toList());
    }


    private CompletionItem completionProperty(String property) {
        String suggestion = property+": ";
        var item = new CompletionItem(suggestion);
        item.setKind(CompletionItemKind.Property);
        return item;
    }


    private List completeSteps(String lineContent) {
        for (String keyword : assessor.documentMap.dialect().getStepKeywords()) {
            if (lineContent.startsWith(keyword)) {
                lineContent = lineContent.substring(keyword.length());
                break;
            }
        }
        var suggestions = assessor.hinter.getExpandedAvailableSteps();
        if (suggestions.isEmpty()) {
            logger.debug(
                "no steps available! used configuration for hinter is:\n{}",
                assessor.effectiveConfiguration
            );
        }
        if (suggestions.size() > assessor.maxSuggestions) {
            suggestions = assessor.hinter.getCompactAvailableSteps();
        }
        String suggestionPrefix = lineContent;
        return suggestions.stream()
            .filter(suggestion -> suggestion.startsWith(suggestionPrefix))
            .map(this::completionStep)
            .collect(toList());
    }


    private CompletionItem completionStep(String step) {

        var item = new CompletionItem(step);
        item.setKind(CompletionItemKind.Interface);
        String insertText = step;

        int snippetArgumentCount = 0;
        var stepSnippetPattern = Pattern.compile("\\*|\\{[^\\}]*\\}");
        Matcher m = stepSnippetPattern.matcher(step);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            snippetArgumentCount ++;
            String capture = insertText.substring(m.start(), m.end());
            capture = capture.replace("}", "\\}");
            capture = "${"+snippetArgumentCount+":"+capture+"}";
            m.appendReplacement(sb, Matcher.quoteReplacement(capture));
        }
        m.appendTail(sb);

        if (snippetArgumentCount > 0) {
            item.setInsertText(sb.toString());
            item.setInsertTextFormat(InsertTextFormat.Snippet);
        }

        item.setDocumentation(step);
        item.setDetail(assessor.hinter.getStepProviderByDefinition(step));
        return item;
    }


    private CompletionItem completionItem(String suggestion, CompletionItemKind kind) {
        var item = new CompletionItem(suggestion);
        item.setKind(kind);
        return item;
    }


    private List completeKeywords(int lineNumber, String strippedLine) {
        return assessor.documentMap.followingKeywords(lineNumber-1).stream()
            .filter(k -> k.startsWith(strippedLine))
            .map(keyword -> completionItem(keyword,CompletionItemKind.Keyword))
            .collect(toList());
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy