package org.fandev.lang.fan.parameterInfo; import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.completion.JavaCompletionUtil; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupItem; import com.intellij.lang.parameterInfo.*; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import org.fandev.lang.fan.psi.FanElement; import org.fandev.lang.fan.psi.api.FanResolveResult; import org.fandev.lang.fan.psi.api.statements.FanVariable; import org.fandev.lang.fan.psi.api.statements.FanDefaultValue; import org.fandev.lang.fan.psi.api.statements.params.FanParameter; import org.fandev.lang.fan.psi.api.statements.typeDefs.members.FanMethod; import org.fandev.lang.fan.psi.api.statements.arguments.FanArgumentList; import org.fandev.lang.fan.psi.api.statements.arguments.FanArgument; import org.fandev.lang.fan.psi.api.statements.expressions.FanReferenceExpression; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; /** * Date: Sep 14, 2009 * Time: 11:42:19 PM * * @author Dror Bereznitsky */ public class FanParameterInfoHandler implements ParameterInfoHandler<FanElement, FanResolveResult> { public boolean couldShowInLookup() { return true; } public Object[] getParametersForLookup(final LookupElement item, final ParameterInfoContext context) { final List<? extends PsiElement> elements = JavaCompletionUtil.getAllPsiElements((LookupItem) item); if (elements != null) { final List<PsiMethod> methods = new ArrayList<PsiMethod>(); for (final PsiElement element : elements) { if (element instanceof PsiMethod) { methods.add((PsiMethod) element); } } return methods.toArray(new Object[0]); } return null; } public Object[] getParametersForDocumentation(final FanResolveResult p, final ParameterInfoContext context) { return new Object[0]; } public FanElement findElementForParameterInfo(final CreateParameterInfoContext context) { return findAnchorElement(context.getEditor().getCaretModel().getOffset(), context.getFile()); } public void showParameterInfo(@NotNull final FanElement place, final CreateParameterInfoContext context) { final PsiElement parent = place.getParent(); FanResolveResult[] variants = FanResolveResult.EMPTY_ARRAY; if (parent instanceof FanReferenceExpression) { variants = ((FanReferenceExpression) parent).getSameNameVariants(); } context.setItemsToShow(variants); context.showHint(place, place.getTextRange().getStartOffset(), this); } public FanElement findElementForUpdatingParameterInfo(final UpdateParameterInfoContext context) { return findAnchorElement(context.getEditor().getCaretModel().getOffset(), context.getFile()); } public void updateParameterInfo(@NotNull final FanElement o, final UpdateParameterInfoContext context) { } public String getParameterCloseChars() { return ",){}"; } public boolean tracksParameterIndex() { return true; } public void updateUI(final FanResolveResult resolveResult, final ParameterInfoUIContext context) { final CodeInsightSettings settings = CodeInsightSettings.getInstance(); final PsiNamedElement element = (PsiNamedElement) resolveResult.getElement(); if (element == null || !element.isValid()) { context.setUIComponentEnabled(false); return; } int highlightStartOffset = -1; int highlightEndOffset = -1; final StringBuffer buffer = new StringBuffer(); if (element instanceof PsiMethod) { final FanMethod method = (FanMethod) element; if (settings.SHOW_FULL_SIGNATURES_IN_PARAMETER_INFO) { if (!method.isConstructor()) { final PsiType returnType = method.getReturnType(); if (returnType != null) { buffer.append(returnType.getPresentableText()); buffer.append(" "); } } buffer.append(element.getName()); buffer.append("("); } final int currentParameter = context.getCurrentParameterIndex(); final PsiParameter[] parms = method.getParameterList().getParameters(); int numParams = parms.length; if (numParams > 0) { final PsiSubstitutor substitutor = resolveResult.getSubstitutor(); for (int j = 0; j < numParams; j++) { final FanParameter parm = (FanParameter) parms[j]; final int startOffset = buffer.length(); appendParameterText(parm, substitutor, buffer); final int endOffset = buffer.length(); if (j < numParams - 1) { buffer.append(", "); } if (context.isUIComponentEnabled() && j == currentParameter) { highlightStartOffset = startOffset; highlightEndOffset = endOffset; } } } else { buffer.append("no parameters"); } if (settings.SHOW_FULL_SIGNATURES_IN_PARAMETER_INFO) { buffer.append(")"); } } else if (element instanceof PsiClass) { buffer.append("no parameters"); } else if (element instanceof FanVariable) { final PsiType type = ((FanVariable) element).getType(); //TODO [dror] hanlde closures here } final boolean isDeprecated = resolveResult instanceof PsiDocCommentOwner && ((PsiDocCommentOwner) resolveResult).isDeprecated(); context.setupUIComponentPresentation( buffer.toString(), highlightStartOffset, highlightEndOffset, !context.isUIComponentEnabled(), isDeprecated, false, context.getDefaultParameterColor() ); } private FanElement findAnchorElement(final int offset, final PsiFile file) { final PsiElement element = file.findElementAt(offset); if (element == null) { return null; } final FanArgument arg = PsiTreeUtil.getParentOfType(element, FanArgument.class); if (arg != null) { final FanElement argList = arg.getArgumentList(); if (argList != null) { return argList; } } return null; } private void appendParameterText(final FanParameter parameter, final PsiSubstitutor substitutor, final StringBuffer buffer) { final PsiType t = parameter.getType(); final PsiType paramType = substitutor.substitute(t); buffer.append(paramType.getPresentableText()); final String name = parameter.getName(); if (name != null) { buffer.append(" "); buffer.append(name); } final FanDefaultValue defaultValue = parameter.getDefaultValue(); if (defaultValue != null) { buffer.append(" ("); buffer.append(defaultValue.getText()); buffer.append(")"); } } }