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

ai.vespa.schemals.lsp.schema.codeaction.provider.QuickFixProvider Maven / Gradle / Ivy

There is a newer version: 8.441.21
Show newest version
package ai.vespa.schemals.lsp.schema.codeaction.provider;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.jsonrpc.messages.Either;

import ai.vespa.schemals.common.FileUtils;
import ai.vespa.schemals.common.SchemaDiagnostic;
import ai.vespa.schemals.common.SchemaDiagnostic.DiagnosticCode;
import ai.vespa.schemals.common.StringUtils;
import ai.vespa.schemals.context.EventCodeActionContext;
import ai.vespa.schemals.index.Symbol;
import ai.vespa.schemals.index.Symbol.SymbolType;
import ai.vespa.schemals.lsp.schema.codeaction.utils.CodeActionUtils;
import ai.vespa.schemals.lsp.schema.rename.SchemaRename;
import ai.vespa.schemals.parser.ast.NL;
import ai.vespa.schemals.parser.ast.RBRACE;
import ai.vespa.schemals.parser.ast.attributeElm;
import ai.vespa.schemals.parser.ast.dataType;
import ai.vespa.schemals.parser.ast.fieldBodyElm;
import ai.vespa.schemals.parser.ast.fieldElm;
import ai.vespa.schemals.parser.ast.indexInsideField;
import ai.vespa.schemals.parser.ast.indexingElm;
import ai.vespa.schemals.parser.ast.inheritsDocument;
import ai.vespa.schemals.parser.ast.inheritsRankProfile;
import ai.vespa.schemals.parser.ast.openLbrace;
import ai.vespa.schemals.parser.ast.rootSchema;
import ai.vespa.schemals.parser.ast.rootSchemaItem;
import ai.vespa.schemals.schemadocument.DocumentManager;
import ai.vespa.schemals.schemadocument.SchemaDocument;
import ai.vespa.schemals.tree.CSTUtils;
import ai.vespa.schemals.tree.Node;
import ai.vespa.schemals.tree.SchemaNode;

/**
 * QuickfixAction
 * Responsible for giving quickfixes for the given code action request
 */
public class QuickFixProvider implements CodeActionProvider {

    private CodeAction basicQuickFix(String title, Diagnostic fixFor) {
        CodeAction action = new CodeAction();
        action.setTitle(title);
        action.setKind(CodeActionKind.QuickFix);
        action.setDiagnostics(List.of(fixFor));
        return action;
    }

    private CodeAction fixSchemaNameSameAsFile(EventCodeActionContext context, Diagnostic diagnostic) {
        String requiredName = FileUtils.schemaNameFromPath(context.document.getFileURI());
        CodeAction action = basicQuickFix("Rename schema to " + requiredName,  diagnostic);
        action.setEdit(SchemaRename.rename(context, requiredName));
        action.setIsPreferred(true);

        return action;
    }

    private CodeAction fixDocumentNameSameAsSchema(EventCodeActionContext context, Diagnostic diagnostic) {
        if (!(context.document instanceof SchemaDocument)) return null; // basically unreachable
        SchemaDocument document = (SchemaDocument)context.document;
        if (document.getSchemaIdentifier() == null) return null; // quickfix impossible

        CodeAction action = basicQuickFix("Rename document to " + document.getSchemaIdentifier(), diagnostic);
        action.setEdit(CodeActionUtils.simpleEdit(context, diagnostic.getRange(), document.getSchemaIdentifier()));
        action.setIsPreferred(true);

        return action;
    }

    private Position firstPositionInBlock(Node blockNode) {
        for (Node child : blockNode) {
            if (child.isASTInstance(openLbrace.class)) {
                return child.get(0).getRange().getEnd();
            }
        }
        return null;
    }

    private Node findRootSchemaItemNode(Node start) {
        Node rootSchemaItemNode = start;

        while (rootSchemaItemNode != null) {
            if (rootSchemaItemNode.isASTInstance(rootSchemaItem.class)) break;
            rootSchemaItemNode = rootSchemaItemNode.getParent();
        }
        return rootSchemaItemNode;
    }

    /**
     * Provides quick fix for trying to do dot syntax on a reference field. 
     * @param context
     * @param diagnostic
     * @return A CodeAction which will provide an import field statement and rename the field access.
     */
    private CodeAction fixAccessUnimportedField(EventCodeActionContext context, Diagnostic diagnostic) {
        Node offendingNode = CSTUtils.getSymbolAtPosition(context.document.getRootNode(), context.position);
        if (offendingNode == null) return null;

        Node referenceFieldNode = offendingNode.getPreviousSibling();

        if (referenceFieldNode == null)return null;
        if (!referenceFieldNode.hasSymbol()) return null;


        String newFieldName = referenceFieldNode.getSymbol().getShortIdentifier() + "_" + offendingNode.getSymbol().getShortIdentifier();

        Node rootSchemaItemNode = findRootSchemaItemNode(offendingNode);
        if (rootSchemaItemNode == null) return null; // likely inside a rootDocument, where import field is impossible

        Position insertPosition = rootSchemaItemNode.getRange().getEnd();
        String indentString = StringUtils.getIndentString(context.document.getCurrentContent(), rootSchemaItemNode);
        int indent = StringUtils.countSpaceIndents(indentString);

        if (rootSchemaItemNode.getPreviousSibling() != null)insertPosition = rootSchemaItemNode.getPreviousSibling().getRange().getEnd();

        CodeAction action = basicQuickFix("Import field " + offendingNode.getSymbol().getShortIdentifier(), diagnostic);

        action.setEdit(CodeActionUtils.simpleEditList(context, List.of(
            new TextEdit(new Range(insertPosition, insertPosition), 
                StringUtils.spaceIndent(indent) +
                "import field " + referenceFieldNode.getSymbol().getShortIdentifier() + "." + 
                                       offendingNode.getSymbol().getShortIdentifier() + " as " +
                                       newFieldName + " {} \n\n"),
            new TextEdit(CSTUtils.unionRanges(offendingNode.getRange(), referenceFieldNode.getRange()), newFieldName)
        )));

        return action;
    }

    private CodeAction fixDocumentlessSchema(EventCodeActionContext context, Diagnostic diagnostic) {
        if (!(context.document instanceof SchemaDocument)) return null; // basically unreachable
        SchemaDocument document = (SchemaDocument)context.document;
        if (document.getSchemaIdentifier() == null) return null; // quickfix impossible
        String schemaName = document.getSchemaIdentifier();
        CodeAction action = basicQuickFix("Insert document definition '" + schemaName + "'", diagnostic);

        Node rootSchemaNode = document.getRootNode().get(0);
        Position insertPosition = firstPositionInBlock(rootSchemaNode);

        if (insertPosition == null) {
            insertPosition = CSTUtils.addPositions(diagnostic.getRange().getStart(), new Position(1, 0)); // one line below
            insertPosition.setCharacter(0);
        }
        Node offendingNode = CSTUtils.getNodeAtPosition(context.document.getRootNode(), diagnostic.getRange().getStart());
        String indentString = StringUtils.getIndentString(context.document.getCurrentContent(), offendingNode);
        int indent = StringUtils.countSpaceIndents(indentString) + StringUtils.TAB_SIZE;
        action.setEdit(CodeActionUtils.simpleEditList(context, List.of(
                new TextEdit(new Range(insertPosition, insertPosition),  
                    "\n" + StringUtils.spaceIndent(indent) + "document " + schemaName + " {\n"
                         + StringUtils.spaceIndent(indent + StringUtils.TAB_SIZE) + "\n" + 
                    StringUtils.spaceIndent(indent) + "}")
        )));

        action.setIsPreferred(true);

        return action;
    }

    /**
     * Provides quick fix for 'field foo type reference<document>' and forgot to put indexing: attribute.
     * @param context
     * @param diagnostic
     * @return The CodeAction providing the quick fix.
     */
    private CodeAction fixDocumentReferenceAttribute(EventCodeActionContext context, Diagnostic diagnostic) {
        Node fieldIdentifierNode = CSTUtils.getSymbolAtPosition(context.document.getRootNode(), context.position);
        if (fieldIdentifierNode == null) return null;

        // TODO: maybe append to existing indexing script if possible
        //       Also works poorly for fields outside document, since their indexing scripts require input.
        Position insertPosition = firstPositionInBlock(fieldIdentifierNode.getParent());
        if (insertPosition == null)return null;

        CodeAction action = basicQuickFix("Set indexing to 'attribute' for field " + fieldIdentifierNode.getSymbol().getShortIdentifier(), diagnostic);

        String indentString = StringUtils.getIndentString(context.document.getCurrentContent(),fieldIdentifierNode.getParent());
        int indent = StringUtils.countSpaceIndents(indentString);

        action.setEdit(CodeActionUtils.simpleEdit(context, new Range(insertPosition, insertPosition), 
            "\n" + StringUtils.spaceIndent(indent + StringUtils.TAB_SIZE) + 
            "indexing: attribute\n" + StringUtils.spaceIndent(indent)
        ));

        return action;
    }

    /**
     * Provides quick fix for importing a field that is not an attribute.
     * @param context
     * @param diagnostic
     * @return A CodeAction that will set indexing to attribute for the original field.
     */
    private CodeAction fixImportFieldAttribute(EventCodeActionContext context, Diagnostic diagnostic) {

        Node importReferenceNode = CSTUtils.getSymbolAtPosition(context.document.getRootNode(), context.position);
        if (importReferenceNode == null) return null;

        Symbol referenceSymbol = importReferenceNode.getSymbol();

        Optional definitionSymbol = context.schemaIndex.getSymbolDefinition(referenceSymbol);

        if (definitionSymbol.isEmpty()) return null;

        Node definitionFieldElm = definitionSymbol.get().getNode().getParent();

        DocumentManager definitionDocument = context.scheduler.getDocument(definitionSymbol.get().getFileURI());

        Position insertPosition = firstPositionInBlock(definitionFieldElm);
        CodeAction action = basicQuickFix("Set indexing to 'attribute' for field " + definitionSymbol.get().getLongIdentifier(), diagnostic);

        String indentString = StringUtils.getIndentString(definitionDocument.getCurrentContent(), definitionFieldElm);
        int indent = StringUtils.countSpaceIndents(indentString);

        action.setEdit(CodeActionUtils.simpleEdit(context, new Range(insertPosition, insertPosition), 
            "\n" + StringUtils.spaceIndent(indent + StringUtils.TAB_SIZE) +
            "indexing: attribute\n" + StringUtils.spaceIndent(indent),
            definitionDocument
        ));

        return action;
    }

    private CodeAction fixExplicitlyInheritDocument(EventCodeActionContext context, Diagnostic diagnostic) {
        Node offendingNode = CSTUtils.getSymbolAtPosition(context.document.getRootNode(), context.position);
        if (offendingNode == null) return null;

        Symbol schemaReferenceSymbol = offendingNode.getSymbol();

        String mySchemaIdentifier = offendingNode.getParent().get(1).getText();

        Optional myDocumentDefinition = context.schemaIndex.findSymbol(null, SymbolType.DOCUMENT, mySchemaIdentifier);

        // findSymbol on DOCUMENT may return SCHEMA. In that case we are not interested
        if (myDocumentDefinition.isEmpty() || myDocumentDefinition.get().getType() != SymbolType.DOCUMENT) return null;

        Node documentIdentifierNode = myDocumentDefinition.get().getNode();

        CodeAction action = basicQuickFix("Inherit document '" + schemaReferenceSymbol.getShortIdentifier() + "'", diagnostic);

        action.setEdit(CodeActionUtils.createInheritsEdit(context, documentIdentifierNode, inheritsDocument.class, schemaReferenceSymbol.getShortIdentifier()));

        action.setIsPreferred(true);

        return action;
    }

    private CodeAction fixInheritsStructFieldRedeclared(EventCodeActionContext context, Diagnostic diagnostic) {
        Node offendingNode = CSTUtils.getSymbolAtPosition(context.document.getRootNode(), context.position);
        if (offendingNode == null) return null;

        CodeAction action = basicQuickFix("Remove field declaration '" + offendingNode.getText() + "'", diagnostic);
        Range fieldRange = offendingNode.getParent().getRange();

        action.setEdit(CodeActionUtils.simpleEdit(context, fieldRange, ""));

        return action;
    }

    private CodeAction fixAnnotationReferenceOutsideAnnotation(EventCodeActionContext context, Diagnostic diagnostic) {
        Node offendingNode = CSTUtils.getNodeAtPosition(context.document.getRootNode(), context.position);
        if (offendingNode == null) return null;

        Node fieldElmNode = offendingNode;

        while (fieldElmNode != null && !fieldElmNode.isASTInstance(fieldElm.class)) fieldElmNode = fieldElmNode.getParent();

        if (fieldElmNode == null) return null;

        CodeAction action = basicQuickFix("Enclose field in annotation", diagnostic);

        String fieldBody = fieldElmNode.getText().replace("\n", "\n" + StringUtils.spaceIndent(StringUtils.TAB_SIZE));

        String indentString = StringUtils.getIndentString(context.document.getCurrentContent(), fieldElmNode);
        int indent = StringUtils.countSpaceIndents(indentString);

        action.setEdit(CodeActionUtils.simpleEdit(context, fieldElmNode.getRange(), 
            "annotation myannotation {\n" + 
            StringUtils.spaceIndent(indent + StringUtils.TAB_SIZE) + fieldBody + "\n"
            + StringUtils.spaceIndent(indent) + "}"
        ));

        return action;
    }

    private CodeAction fixDeprecatedArraySyntax(EventCodeActionContext context, Diagnostic diagnostic) {
        Node tokenNode = CSTUtils.getLeafNodeAtPosition(context.document.getRootNode(), context.position);
        if (tokenNode == null) return null;
        if (!tokenNode.getParent().getParent().isASTInstance(dataType.class))return null;

        String typeText = tokenNode.getText();
        CodeAction action = basicQuickFix("Change to array<" + typeText + ">", diagnostic);

        action.setEdit(CodeActionUtils.simpleEdit(context, tokenNode.getParent().getParent().getRange(), "array<" + typeText + ">"));
        action.setIsPreferred(true);
        return action;
    }

    private CodeAction fixDeprecatedTokenSearch(EventCodeActionContext context, Diagnostic diagnostic) {
        CodeAction action = basicQuickFix("Change to schema", diagnostic);
        action.setEdit(CodeActionUtils.simpleEdit(context, diagnostic.getRange(), "schema"));
        action.setIsPreferred(true);
        return action;
    }

    /**
     * Quick fix for using attribute some_name_other_than_field_name in a field. Will create a new field outside 
     * the document with the specified attribute, using the original field as input and type.
     * @param context
     * @param diagnostic
     * @param code
     * @return CodeAction supplying the edits.
     */
    private CodeAction fixDeprecatedTokenAttributeOrIndex(EventCodeActionContext context, Diagnostic diagnostic, DiagnosticCode code) {
        // TODO: actually create an enclosing schema if it doesn't exist?
        if (!context.document.getRootNode().get(0).isASTInstance(rootSchema.class)) return null;

        Class offendingBodyClass;
        String replacementKind;

        if (code == DiagnosticCode.DEPRECATED_TOKEN_ATTRIBUTE) {
            offendingBodyClass = attributeElm.class;
            replacementKind = "attribute";
        } else {
            offendingBodyClass = indexInsideField.class;
            replacementKind = "index";
        }

        Node offendingNode = CSTUtils.getNodeAtPosition(context.document.getRootNode(), context.position);

        // Find the field definition containing the error as well as its data type
        Optional fieldDefinition = CSTUtils.findScope(offendingNode);
        if (fieldDefinition.isEmpty()) return null;

        Optional dataTypeNode = context.schemaIndex.fieldIndex().getFieldDataTypeNode(fieldDefinition.get());

        // use some arbitrary default, the generated field will most likely require manual editing anyways
        String dataTypeString = dataTypeNode.isPresent() ? dataTypeNode.get().getText() : "string"; 

        // Find the node containing the entire index or attribute statement
        Node offendingBodyElmNode = offendingNode;
        while (offendingBodyElmNode != null && !offendingBodyElmNode.isASTInstance(offendingBodyClass)) {
            offendingBodyElmNode = offendingBodyElmNode.getParent();
        }
        if (offendingBodyElmNode == null) return null;

        // Find the rootSchemaItemNode containing the document so we can insert after
        Node rootSchemaItemNode = findRootSchemaItemNode(offendingNode);
        if (rootSchemaItemNode == null) return null;


        // Calculate required indent and insert position
        String insertIndentString = StringUtils.getIndentString(context.document.getCurrentContent(), rootSchemaItemNode);
        int indent = StringUtils.countSpaceIndents(insertIndentString);
        Range insertPosition = new Range(rootSchemaItemNode.getRange().getEnd(), rootSchemaItemNode.getRange().getEnd());


        // subtract indent from the index/attribute block to match the new indent outside document
        String offendingBodyIndentString = StringUtils.getIndentString(context.document.getCurrentContent(), offendingBodyElmNode);
        int bodyIndentDelta = indent + StringUtils.TAB_SIZE - StringUtils.countSpaceIndents(offendingBodyIndentString);
        String offendingBodyText = StringUtils.addIndents(
            offendingBodyElmNode.getText().replace("\t", StringUtils.spaceIndent(StringUtils.TAB_SIZE)),
            bodyIndentDelta
        );

        CodeAction action = basicQuickFix("Create field '" + offendingNode.getText() + "' outside document", diagnostic);
        action.setEdit(CodeActionUtils.simpleEditList(context, List.of(
            new TextEdit(offendingBodyElmNode.getRange(), ""),
            new TextEdit(insertPosition, "\n" + StringUtils.spaceIndent(indent) +
                "field " + offendingNode.getText() + " type " + dataTypeString + " {\n" +
                StringUtils.spaceIndent(indent + StringUtils.TAB_SIZE) + "# TODO: Auto-generated indexing statement\n" +
                // Fields outside document needs an indexing statement to be useful
                StringUtils.spaceIndent(indent + StringUtils.TAB_SIZE) + "indexing: input " + fieldDefinition.get().getShortIdentifier() + " | " + replacementKind + "\n" +
                StringUtils.spaceIndent(indent + StringUtils.TAB_SIZE) + offendingBodyText + "\n" + 
                StringUtils.spaceIndent(indent) + "}")
        )));

        action.setIsPreferred(true);

        return action;
    }

    private CodeAction fixFeaturesInheritsNonParent(EventCodeActionContext context, Diagnostic diagnostic) {
        Node offendingNode = CSTUtils.getSymbolAtPosition(context.document.getRootNode(), context.position);
        if (offendingNode == null || offendingNode.getSymbol().getScope() == null) return null;

        Symbol rankProfileSymbol = offendingNode.getSymbol().getScope();
        CodeAction action = basicQuickFix("Inherit rank-profile " + offendingNode.getText() + " from " + rankProfileSymbol.getShortIdentifier(), diagnostic);
        action.setEdit(CodeActionUtils.createInheritsEdit(context, rankProfileSymbol.getNode(), inheritsRankProfile.class, offendingNode.getText()));
        return action;
    }

    private CodeAction fixFieldArgumentMissingIndexingType(EventCodeActionContext context, Diagnostic diagnostic) {

        Node offendingNode = CSTUtils.getSymbolAtPosition(context.document.getRootNode(), context.position);
        if (offendingNode == null || !offendingNode.hasSymbol()) return null;
        Optional symbol = context.schemaIndex.findSymbol(offendingNode.getSymbol());
        if (symbol.isEmpty()) return null;

        Node node = symbol.get().getNode().getParent();

        Optional indexingNode = Optional.empty();
        for (Node child : node) {
            if (child.isASTInstance(fieldBodyElm.class)) {
                Node grandChild = child.get(0);
                if (grandChild != null && grandChild.isASTInstance(indexingElm.class)) {
                    indexingNode = Optional.of(grandChild);
                }
            }
        }

        CodeAction action = basicQuickFix("Add attribute as indexing attribute", diagnostic);

        if (indexingNode.isPresent()) {
            action.setEdit(CodeActionUtils.simpleEdit(context, indexingNode.get().getRange().getEnd(), " | attribute"));

        } else {
            // Add indexing node as well
            Optional rBraceNode = Optional.empty();

            for (int i = 0; i < node.size(); i++) {
                Node child = node.get(i);
                if (child.isASTInstance(RBRACE.class)) {
                    rBraceNode = Optional.of(child);
                    break;
                }
            }

            if (rBraceNode.isEmpty()) return null;

            // Calculate indent
            Node fieldKeywordNode = node.get(0);
            if (fieldKeywordNode == null) return null;

            String insertIndentString = StringUtils.getIndentString(context.document.getCurrentContent(), fieldKeywordNode);
            int indent = StringUtils.countSpaceIndents(insertIndentString);

            String newText = StringUtils.spaceIndent(StringUtils.TAB_SIZE) + "indexing: attribute\n" + StringUtils.spaceIndent(indent);

            // Check is a leading new line is necessary
            Node prevSibling = rBraceNode.get().getPrevious();
            if (prevSibling == null) return null;
            boolean newLineNecessary = false;
            if (!prevSibling.isASTInstance(NL.class)) {
                if (prevSibling.isASTInstance(openLbrace.class)) {
                    Node lastLbraceChild = prevSibling.get(prevSibling.size() - 1);
                    if (!lastLbraceChild.isASTInstance(NL.class)) {
                        newLineNecessary = true;
                    }
                } else {
                    newLineNecessary = true;
                }
            }

            if (newLineNecessary) {
                newText = "\n" + StringUtils.spaceIndent(indent) + newText;
            }

            action.setEdit(CodeActionUtils.simpleEdit(context, rBraceNode.get().getRange().getStart(), newText));
        }

        return action;
    }

	@Override
	public List> getActions(EventCodeActionContext context) {
        List> result = new ArrayList<>();

        for (Diagnostic diagnostic : context.diagnostics) {
            if (diagnostic.getCode() == null) {
                // unhandled
                continue;
            }

            if (diagnostic.getCode().isLeft()) continue; // we don't to string codes

            DiagnosticCode code = SchemaDiagnostic.codeFromInt(diagnostic.getCode().getRight());

            switch (code) {
                case SCHEMA_NAME_SAME_AS_FILE:
                    result.add(Either.forRight(fixSchemaNameSameAsFile(context, diagnostic)));
                    break;
                case DOCUMENT_NAME_SAME_AS_SCHEMA:
                    result.add(Either.forRight(fixDocumentNameSameAsSchema(context, diagnostic)));
                    break;
                case ACCESS_UNIMPORTED_FIELD:
                    result.add(Either.forRight(fixAccessUnimportedField(context, diagnostic)));
                    break;
                case DOCUMENTLESS_SCHEMA:
                    result.add(Either.forRight(fixDocumentlessSchema(context, diagnostic)));
                    break;
                case DOCUMENT_REFERENCE_ATTRIBUTE:
                    result.add(Either.forRight(fixDocumentReferenceAttribute(context, diagnostic)));
                    break;
                case IMPORT_FIELD_ATTRIBUTE:
                    result.add(Either.forRight(fixImportFieldAttribute(context, diagnostic)));
                    break;
                case EXPLICITLY_INHERIT_DOCUMENT:
                    result.add(Either.forRight(fixExplicitlyInheritDocument(context, diagnostic)));
                    break;
                case INHERITS_STRUCT_FIELD_REDECLARED:
                    result.add(Either.forRight(fixInheritsStructFieldRedeclared(context, diagnostic)));
                    break;
                case ANNOTATION_REFERENCE_OUTSIDE_ANNOTATION:
                    result.add(Either.forRight(fixAnnotationReferenceOutsideAnnotation(context, diagnostic)));
                    break;
                case DEPRECATED_ARRAY_SYNTAX:
                    result.add(Either.forRight(fixDeprecatedArraySyntax(context, diagnostic)));
                    break;
                case DEPRECATED_TOKEN_SEARCH:
                    result.add(Either.forRight(fixDeprecatedTokenSearch(context, diagnostic)));
                    break;
                case DEPRECATED_TOKEN_ATTRIBUTE:
                case DEPRECATED_TOKEN_INDEX:
                    result.add(Either.forRight(fixDeprecatedTokenAttributeOrIndex(context, diagnostic, code)));
                    break;
                case FEATURES_INHERITS_NON_PARENT:
                    result.add(Either.forRight(fixFeaturesInheritsNonParent(context, diagnostic)));
                    break;
                case FIELD_ARGUMENT_MISSING_INDEXING_TYPE:
                    result.add(Either.forRight(fixFieldArgumentMissingIndexingType(context, diagnostic)));
                    break;
                default:
                    break;
            }
        }

        return result;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy