Package ro.redeul.google.go.lang.parameterInfo

Source Code of ro.redeul.google.go.lang.parameterInfo.GoParameterInfoHandler$ParameterInfo

package ro.redeul.google.go.lang.parameterInfo;

import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.lang.parameterInfo.*;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import ro.redeul.google.go.lang.parser.GoElementTypes;
import ro.redeul.google.go.lang.psi.GoPsiElement;
import ro.redeul.google.go.lang.psi.expressions.GoExpr;
import ro.redeul.google.go.lang.psi.expressions.primary.GoCallOrConvExpression;
import ro.redeul.google.go.lang.psi.expressions.primary.GoLiteralExpression;
import ro.redeul.google.go.lang.psi.toplevel.GoFunctionDeclaration;

import java.util.List;

import static ro.redeul.google.go.lang.documentation.DocumentUtil.getFunctionParameterRangeInText;
import static ro.redeul.google.go.lang.documentation.DocumentUtil.getFunctionPresentationText;
import static ro.redeul.google.go.lang.psi.utils.GoExpressionUtils.getCallParenthesesTextRange;
import static ro.redeul.google.go.lang.psi.utils.GoExpressionUtils.resolveToFunctionDeclaration;
import static ro.redeul.google.go.lang.psi.utils.GoPsiUtils.*;

public class GoParameterInfoHandler implements ParameterInfoHandler<GoPsiElement, GoParameterInfoHandler.ParameterInfo> {
    @Override
    public boolean couldShowInLookup() {
        return true;
    }

    @Override
    public Object[] getParametersForLookup(LookupElement item, ParameterInfoContext context) {
        return new Object[0];
    }

    @Override
    public Object[] getParametersForDocumentation(ParameterInfo p, ParameterInfoContext context) {
        return new Object[0];
    }

    @Override
    public GoPsiElement findElementForParameterInfo(CreateParameterInfoContext context) {
        int offset = context.getEditor().getCaretModel().getOffset();
        ParameterInfo pi = findAnchorElement(offset, context.getFile());
        if (pi == null) {
            return null;
        }
        context.setItemsToShow(new Object[]{pi});
        return pi.call;
    }

    @Override
    public GoPsiElement findElementForUpdatingParameterInfo(UpdateParameterInfoContext context) {
        int offset = context.getEditor().getCaretModel().getOffset();
        ParameterInfo pi = findAnchorElement(offset, context.getFile());
        if (pi == null) {
            return null;
        }

        Object[] psi = context.getObjectsToView();
        if (psi == null || psi.length == 0 || !(psi[0] instanceof ParameterInfo)) {
            return null;
        }

        ParameterInfo oldPi = (ParameterInfo) psi[0];
        if (pi.call != oldPi.call || pi.currentIndex < 0) {
            return null;
        }

        oldPi.currentIndex = pi.currentIndex;
        return pi.call;
    }

    private GoCallOrConvExpression findFunctionCallParent(PsiElement element, int offset) {
        GoCallOrConvExpression call = findParentOfType(element, GoCallOrConvExpression.class);
        if (call == null) {
            return null;
        }

        List<GoExpr> exprs = findChildrenOfType(call, GoExpr.class);
        if (exprs.isEmpty()) {
            return null;
        }

        PsiElement child = exprs.get(0);
        if (!(child instanceof GoLiteralExpression)) {
            return null;
        }

        // If the caret is on function name, current function parameters info shouldn't be shown.
        // Let's see if the function call is a parameter of another function call.
        if (child.getTextRange().contains(offset)) {
            return findFunctionCallParent(call.getParent(), offset);
        }
        return call;
    }

    private ParameterInfo findAnchorElement(int offset, PsiFile file) {
        PsiElement element = file.findElementAt(offset);
        GoCallOrConvExpression call = findFunctionCallParent(element, offset);
        GoFunctionDeclaration func = resolveToFunctionDeclaration(call);
        if (func == null) {
            return null;
        }

        PsiElement expressionList = findChildOfType(call, GoElementTypes.EXPRESSION_LIST);
        List<PsiElement> commas = findChildrenOfType(expressionList, GoElementTypes.oCOMMA);
        int currentIndex = commas.size();
        for (int i = 0; i < commas.size(); i++) {
            if (offset < commas.get(i).getTextRange().getEndOffset()) {
                currentIndex = i;
                break;
            }
        }

        if (!getCallParenthesesTextRange(call).contains(offset)) {
            currentIndex = -1;
        }

        return new ParameterInfo(func, call, currentIndex);
    }

    @Override
    public void showParameterInfo(@NotNull GoPsiElement element, CreateParameterInfoContext context) {
        context.showHint(element, element.getTextRange().getStartOffset(), this);
    }

    @Override
    public void updateParameterInfo(@NotNull GoPsiElement o, UpdateParameterInfoContext context) {
        Object[] psi = context.getObjectsToView();
        if (psi == null || psi.length == 0 || !(psi[0] instanceof ParameterInfo)) {
            return;
        }
        ParameterInfo pi = (ParameterInfo) psi[0];
        context.setCurrentParameter(pi.currentIndex);
    }

    @Override
    public void updateUI(ParameterInfo p, ParameterInfoUIContext context) {
        String text = getFunctionPresentationText(p.functionDeclaration);
        int index = context.getCurrentParameterIndex();
        TextRange range = getFunctionParameterRangeInText(p.functionDeclaration, index);
        context.setupUIComponentPresentation(text,
                range.getStartOffset(), range.getEndOffset(),
                false, false, true, context.getDefaultParameterColor()
        );
    }

    @Override
    public String getParameterCloseChars() {
        return null;
    }

    @Override
    public boolean tracksParameterIndex() {
        return false;
    }

    public static class ParameterInfo {
        public final GoFunctionDeclaration functionDeclaration;

        public final GoCallOrConvExpression call;
        public int currentIndex;

        private ParameterInfo(GoFunctionDeclaration functionDeclaration, GoCallOrConvExpression call,
                              int currentIndex) {
            this.functionDeclaration = functionDeclaration;
            this.call = call;
            this.currentIndex = currentIndex;
        }
    }
}
TOP

Related Classes of ro.redeul.google.go.lang.parameterInfo.GoParameterInfoHandler$ParameterInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.