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

ai.vespa.schemals.lsp.schema.completion.provider.InheritanceCompletion Maven / Gradle / Ivy

There is a newer version: 8.441.21
Show newest version
package ai.vespa.schemals.lsp.schema.completion.provider;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.Position;

import ai.vespa.schemals.context.EventCompletionContext;
import ai.vespa.schemals.index.Symbol;
import ai.vespa.schemals.index.Symbol.SymbolType;
import ai.vespa.schemals.lsp.schema.completion.utils.CompletionUtils;
import ai.vespa.schemals.parser.Token.TokenType;
import ai.vespa.schemals.parser.ast.COMMA;
import ai.vespa.schemals.parser.ast.IDENTIFIER;
import ai.vespa.schemals.parser.ast.identifierStr;
import ai.vespa.schemals.parser.ast.identifierWithDashStr;
import ai.vespa.schemals.tree.CSTUtils;
import ai.vespa.schemals.tree.Node;
import ai.vespa.schemals.tree.SchemaNode;

/**
 * For completing user defined identifiers after "inherits".
 */
public class InheritanceCompletion implements CompletionProvider {
    private Optional match(EventCompletionContext context) {
        Position searchPos = context.startOfWord();
        if (searchPos == null)searchPos = context.position;
        Node last = CSTUtils.getLastCleanNode(context.document.getRootNode(), searchPos);
        if (last == null || !last.isSchemaNode()) return Optional.empty();

        if (last.isASTInstance(IDENTIFIER.class))last = last.getParent();
        if (last.isASTInstance(COMMA.class))last = last.getPrevious();


        // Skip previously declared fields in the list
        // to get to the start where we can determine the pattern fields: ...
        while (last != null &&
                (last.isASTInstance(identifierStr.class) || last.isASTInstance(identifierWithDashStr.class)) && 
                (last.getPrevious() != null && last.getPrevious().getSchemaNode().getSchemaType() == TokenType.COMMA)) {
        last = last.getPrevious().getPrevious();
        }

        if (last == null)return Optional.empty();

        searchPos = last.getRange().getStart();

        SchemaNode match = context.document.lexer().matchBackwards(searchPos, 1, false, TokenType.IDENTIFIER, TokenType.INHERITS);

        // edge case for rank profiles.
        if (match != null && match.getParent() != null && match.getParent().getParent() != null && match.getParent().getParent().isASTInstance(identifierWithDashStr.class))
            match = match.getParent().getSchemaNode();

        // Has to be on the same line
        if (match != null && match.getRange().getStart().getLine() == context.position.getLine()
                && match.getParent().hasSymbol()) return Optional.of(match);

        return Optional.empty();
    }

	@Override
	public List getCompletionItems(EventCompletionContext context) {
        Optional matched = match(context);
        if (matched.isEmpty()) return List.of();

        Symbol identifierSymbol = matched.get().getParent().getSymbol();

        List ret = new ArrayList<>();

        boolean defaultSeen = false;
        Symbol scope = (identifierSymbol.getType() == SymbolType.DOCUMENT 
                     || identifierSymbol.getType() == SymbolType.SCHEMA 
                     || identifierSymbol.getType() == SymbolType.RANK_PROFILE) 
                      ? null : identifierSymbol.getScope();

        for (var symbol : context.schemaIndex.listSymbolsInScope(scope, identifierSymbol.getType())) {
            if (symbol.getShortIdentifier().equals(identifierSymbol.getShortIdentifier()))continue; // identifier-based, since symbols may be inaccurate in this context
            ret.add(CompletionUtils.constructBasic(symbol.getShortIdentifier(), symbol.getLongIdentifier()));
            if (symbol.getShortIdentifier().equals("default"))defaultSeen = true;
        }

        if (identifierSymbol.getType() == SymbolType.RANK_PROFILE && !defaultSeen)ret.add(CompletionUtils.constructBasic("default"));

        return ret;
	}

    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy