package com.siberika.idea.pascal.editor; import com.intellij.codeInsight.hints.HintInfo; import com.intellij.codeInsight.hints.InlayInfo; import com.intellij.codeInsight.hints.InlayParameterHintsProvider; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import com.siberika.idea.pascal.lang.psi.PasArgumentList; import com.siberika.idea.pascal.lang.psi.PasCallExpr; import com.siberika.idea.pascal.lang.psi.PasClosureExpr; import com.siberika.idea.pascal.lang.psi.PasExpr; import com.siberika.idea.pascal.lang.psi.PasFormalParameter; import com.siberika.idea.pascal.lang.psi.PasFormalParameterSection; import com.siberika.idea.pascal.lang.psi.PasIndexList; import com.siberika.idea.pascal.lang.psi.PasLiteralExpr; import com.siberika.idea.pascal.lang.psi.PasNamedIdent; import com.siberika.idea.pascal.lang.psi.PascalPsiElement; import com.siberika.idea.pascal.lang.psi.impl.PasField; import com.siberika.idea.pascal.lang.psi.impl.PascalRoutineImpl; import com.siberika.idea.pascal.lang.references.PasReferenceUtil; import kotlin.reflect.jvm.internal.impl.utils.SmartList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.List; import java.util.Set; /** * Author: George Bakhtadze * Date: 27/04/2017 */ public class PascalParameterNameHints implements InlayParameterHintsProvider { @NotNull @Override public List<InlayInfo> getParameterHints(PsiElement psiElement) { if (psiElement instanceof PasCallExpr) { return getParameters((PasCallExpr) psiElement); } else { return Collections.emptyList(); } } @Nullable @Override public HintInfo getHintInfo(PsiElement psiElement) { return null; } @NotNull @Override public Set<String> getDefaultBlackList() { return Collections.emptySet(); } private List<InlayInfo> getParameters(PasCallExpr callExpr) { int count = callExpr.getArgumentList().getExprList().size(); if (count > 0) for (PasField field : PasReferenceUtil.resolveRoutines(callExpr)) { if (field.getElement() instanceof PascalRoutineImpl) { PasFormalParameterSection parameters = ((PascalRoutineImpl) field.getElement()).getFormalParameterSection(); if (parameters != null) { List<String> params = new SmartList<String>(); for (PasFormalParameter parameter : parameters.getFormalParameterList()) { for (PasNamedIdent pasNamedIdent : parameter.getNamedIdentList()) { params.add(pasNamedIdent.getName()); } } if (count == params.size()) { return retrieveInlayInfo(callExpr, params); } } } } return Collections.emptyList(); } private List<InlayInfo> retrieveInlayInfo(PasCallExpr callExpr, List<String> parameters) { List<InlayInfo> res = new SmartList<InlayInfo>(); List<PasExpr> exprList = callExpr.getArgumentList().getExprList(); for (int i = 0; i < exprList.size(); i++) { PasExpr arg = exprList.get(i); PasLiteralExpr literal = PsiTreeUtil.findChildOfType(arg, PasLiteralExpr.class, false); PascalPsiElement root = PsiTreeUtil.getParentOfType(literal, PasArgumentList.class, PasIndexList.class, PasClosureExpr.class); if (root == callExpr.getArgumentList()) { res.add(new InlayInfo(parameters.get(i), arg.getTextRange().getStartOffset())); } } return res; } }