/* * Copyright 2013 Guidewire Software, Inc. */ package gw.plugin.ij.completion; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.intellij.codeInsight.AutoPopupController; import com.intellij.codeInsight.completion.InsertionContext; import com.intellij.codeInsight.completion.JavaCompletionUtil; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementPresentation; import com.intellij.openapi.editor.Document; import com.intellij.psi.PsiFile; import com.intellij.ui.LayeredIcon; import com.intellij.ui.RowIcon; import gw.internal.gosu.parser.IGosuTemplateInternal; import gw.internal.gosu.parser.TypeLord; import gw.lang.reflect.IBlockType; import gw.lang.reflect.IConstructorInfo; import gw.lang.reflect.IFeatureInfo; import gw.lang.reflect.IMethodInfo; import gw.lang.reflect.IParameterInfo; import gw.lang.reflect.IPropertyInfo; import gw.lang.reflect.IType; import gw.lang.reflect.ITypeInfo; import gw.lang.reflect.TypeSystem; import gw.lang.reflect.gs.IGosuClass; import gw.lang.reflect.gs.IGosuEnhancement; import gw.lang.reflect.gs.IGosuProgram; import gw.lang.reflect.gs.IGosuVarPropertyInfo; import gw.lang.reflect.java.IJavaFieldPropertyInfo; import gw.lang.reflect.java.IJavaType; import gw.lang.reflect.module.IModule; import gw.plugin.ij.icons.GosuIcons; import gw.plugin.ij.lang.psi.custom.CustomGosuClass; import gw.plugin.ij.lang.psi.impl.CustomPsiClassCache; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.util.Arrays; import java.util.List; import static com.google.common.collect.Iterables.transform; public class GosuFeatureCallLookupElement extends LookupElement { private final IFeatureInfo _featureInfo; public GosuFeatureCallLookupElement(IFeatureInfo featureInfo) { _featureInfo = featureInfo; } @NotNull @Override public String getLookupString() { return _featureInfo instanceof IMethodInfo ? _featureInfo.getDisplayName() : _featureInfo.getName(); } @NotNull private RowIcon getIcon() { Icon icon = null; IFeatureInfo fi = _featureInfo; IModule mod = TypeSystem.getCurrentModule(); IType ownersType; if( mod == null ) { TypeSystem.pushGlobalModule(); } try { ownersType = fi.getOwnersType(); if( fi instanceof IPropertyInfo ) { if( fi instanceof IJavaFieldPropertyInfo || fi instanceof IGosuVarPropertyInfo ) { icon = GosuIcons.FIELD; } else { icon = GosuIcons.PROPERTY; } } else if( fi instanceof ITypeInfo ) { //## Warning: following call to getPsiClass() is SSSSSSSSSSSSSSLLLLLLLLLLLLLLLOOOOOOOOOOOOWWWWWWWWWWWWWWWW if( !(ownersType instanceof IGosuClass || ownersType instanceof IJavaType || ownersType instanceof IBlockType) ) { CustomGosuClass psiClass = CustomPsiClassCache.instance().getPsiClass( ownersType ); if( psiClass != null ) { icon = psiClass.getIcon( 0 ); } } if( icon == null ) { icon = ownersType.isInterface() ? GosuIcons.INTERFACE : ownersType instanceof IGosuTemplateInternal ? GosuIcons.TEMPLATE : ownersType instanceof IGosuProgram ? GosuIcons.PROGRAM : ownersType instanceof IGosuEnhancement ? GosuIcons.ENHANCEMENT : GosuIcons.CLASS; } } else { icon = GosuIcons.METHOD; } RowIcon rowIcon = new RowIcon(2); LayeredIcon icon2 = new LayeredIcon(2); icon2.setIcon(icon, 0); if ( ownersType instanceof IGosuEnhancement) { icon2.setIcon(GosuIcons.ENH, 1); } rowIcon.setIcon(icon2, 0); return rowIcon; } finally { if( mod == null ) { TypeSystem.popGlobalModule(); } } } @Override public void renderElement(@NotNull LookupElementPresentation presentation) { String typeText = null; if( _featureInfo instanceof IMethodInfo ) { typeText = ((IMethodInfo)_featureInfo).getReturnType().getRelativeName(); } else if( _featureInfo instanceof IPropertyInfo ) { typeText = ((IPropertyInfo)_featureInfo).getFeatureType().getRelativeName(); } else if( _featureInfo instanceof IConstructorInfo ) { typeText = _featureInfo.getOwnersType().getRelativeName(); } else if( _featureInfo instanceof ITypeInfo ) { typeText = getFqn( (ITypeInfo)_featureInfo ); } presentation.setTypeText(typeText); presentation.setItemText(getDisplayString()); presentation.setIcon(getIcon()); } private String getFqn( ITypeInfo ti ) { IModule mod = TypeSystem.getCurrentModule(); if( mod == null ) { TypeSystem.pushGlobalModule(); } try { return TypeLord.getPureGenericType( ti.getOwnersType() ).getName(); } finally { if( mod == null ) { TypeSystem.popGlobalModule(); } } } public String getDisplayString() { if (_featureInfo instanceof IMethodInfo) { final List<IParameterInfo> params = Arrays.asList(((IMethodInfo) _featureInfo).getParameters()); final String strParams = Joiner.on(", ").join(transform(params, new Function<IParameterInfo, String>() { @NotNull @Override public String apply(@NotNull IParameterInfo info) { return info.getDisplayName() + " " + info.getFeatureType().getRelativeName(); } })); return String.format("%s(%s)", _featureInfo.getDisplayName(), strParams); } else { return _featureInfo.getDisplayName(); } } @Override public void handleInsert(@NotNull InsertionContext context) { if (_featureInfo instanceof IMethodInfo) { final Document document = context.getDocument(); final PsiFile file = context.getFile(); //final LookupElement[] allItems = context.getElements(); final boolean overloadsMatter = true; //allItems.length == 1 && getUserData( FORCE_SHOW_SIGNATURE_ATTR ) == null; final boolean hasParams = ((IMethodInfo) _featureInfo).getParameters().length > 0; JavaCompletionUtil.insertParentheses(context, this, overloadsMatter, hasParams); AutoPopupController.getInstance(file.getProject()).autoPopupParameterInfo(context.getEditor(), null); /* final int startOffset = context.getStartOffset(); final OffsetKey refStart = context.trackOffset(startOffset, true); if (shouldInsertTypeParameters(context)) { qualifyMethodCall(file, startOffset, document); insertExplicitTypeParameters(context, refStart); } else if (myCanImportStatic || getAttribute(FORCE_QUALIFY) != null) { context.commitDocument(); if (myCanImportStatic && myShouldImportStatic) { final PsiReferenceExpression ref = PsiTreeUtil.findElementOfClassAtOffset( file, startOffset, PsiReferenceExpression.class, false ); if (ref != null) { ref.bindToElementViaStaticImport(myContainingClass); } return; } qualifyMethodCall(file, startOffset, document); } final PsiType type = method.getReturnType(); if (context.getCompletionChar() == '!' && type != null && PsiType.BOOLEAN.isAssignableFrom(type)) { context.commitDocument(); final int offset = context.getOffset(refStart); final PsiMethodCallExpression methodCall = PsiTreeUtil.findElementOfClassAtOffset(file, offset, PsiMethodCallExpression.class, false); if (methodCall != null) { FeatureUsageTracker.getInstance().triggerFeatureUsed( CodeCompletionFeatures.EXCLAMATION_FINISH); document.insertString(methodCall.getTextRange().getStartOffset(), "!"); } } */ } else { super.handleInsert(context); } } }