Skip to content

Commit

Permalink
Provide completion of class methods when referencing it in an array
Browse files Browse the repository at this point in the history
  • Loading branch information
klesun committed Sep 5, 2017
1 parent 102bc12 commit 2eb6552
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 8 deletions.
63 changes: 63 additions & 0 deletions src/org/klesun/deep_keys/entry/ArrFuncRefPvdr.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.klesun.deep_keys.entry;

import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.CompletionProvider;
import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.psi.PsiElement;
import com.intellij.util.ProcessingContext;
import com.jetbrains.php.PhpIcons;
import com.jetbrains.php.lang.psi.elements.Method;
import com.jetbrains.php.lang.psi.elements.PhpExpression;
import com.jetbrains.php.lang.psi.elements.impl.ArrayCreationExpressionImpl;
import com.jetbrains.php.lang.psi.elements.impl.FunctionReferenceImpl;
import org.jetbrains.annotations.NotNull;
import org.klesun.deep_keys.DeepType;
import org.klesun.deep_keys.helpers.FuncCtx;
import org.klesun.deep_keys.helpers.IFuncCtx;
import org.klesun.deep_keys.helpers.MultiType;
import org.klesun.deep_keys.helpers.SearchContext;
import org.klesun.deep_keys.resolvers.ArrCtorRes;

import java.util.HashSet;
import java.util.Set;

import static org.klesun.lang.Lang.*;

/**
* provides completion of method names in `[Some\ClassName::class, '']`
*/
public class ArrFuncRefPvdr extends CompletionProvider<CompletionParameters>
{
private static LookupElement makeLookup(Method method)
{
return LookupElementBuilder.create(method.getName())
.bold()
.withIcon(PhpIcons.METHOD)
.withTypeText(method.getLocalType(false).toString());
}

@Override
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext processingContext, @NotNull CompletionResultSet result)
{
long startTime = System.nanoTime();
L<Method> methods = opt(parameters.getPosition().getParent())
.fap(literal -> opt(literal.getParent())
.map(arrVal -> arrVal.getParent())
.fap(toCast(ArrayCreationExpressionImpl.class))
.map(arrCtor -> L(arrCtor.getChildren()))
.flt(params -> params.size() == 2)
.flt(params -> literal.isEquivalentTo(params.get(1).getFirstChild()))
.fap(params -> params.gat(0))
.fap(ArrCtorRes::resolveClass)
.map(cls -> L(cls.getMethods()).flt(meth -> meth.isStatic())))
.def(L());

methods.map(m -> makeLookup(m)).fch(result::addElement);
result.addLookupAdvertisement("Press <Page Down> few times to skip built-in suggestions");

long elapsed = System.nanoTime() - startTime;
System.out.println("Resolved in " + (elapsed / 1000000000.0) + " seconds");
}
}
11 changes: 10 additions & 1 deletion src/org/klesun/deep_keys/entry/DeepKeysCbtr.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public DeepKeysCbtr()
this.extend(
CompletionType.BASIC,
PlatformPatterns.psiElement()
.withSuperParent(1, StringLiteralExpression.class)
.withSuperParent(2, ArrayIndex.class),
new DeepKeysPvdr()
);
Expand All @@ -30,9 +31,17 @@ public DeepKeysCbtr()
CompletionType.BASIC,
PlatformPatterns.psiElement()
.withSuperParent(1, StringLiteralExpression.class)
//.withSuperParent(2, ParameterList.class)
.withSuperParent(2, ParameterList.class)
,
new ArrayColumnPvdr()
);
this.extend(
CompletionType.BASIC,
PlatformPatterns.psiElement()
.withSuperParent(1, StringLiteralExpression.class)
.withSuperParent(3, ArrayCreationExpression.class)
,
new ArrFuncRefPvdr()
);
}
}
19 changes: 12 additions & 7 deletions src/org/klesun/deep_keys/resolvers/ArrCtorRes.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ public ArrCtorRes(IFuncCtx ctx)
this.ctx = ctx;
}

public static Opt<PhpClass> resolveClass(PsiElement clsPsi)
{
return opt(clsPsi.getFirstChild())
.fap(toCast(ClassConstantReferenceImpl.class))
.flt(cst -> Objects.equals(cst.getName(), "class"))
.map(cst -> cst.getClassReference())
.fap(toCast(ClassReferenceImpl.class))
.map(clsRef -> clsRef.resolve())
.fap(toCast(PhpClass.class));
}

/** like in [Ns\Employee::class, 'getSalary'] */
private static Opt<Method> resolveMethodFromArray(L<PsiElement> refParts)
{
Expand All @@ -30,13 +41,7 @@ private static Opt<Method> resolveMethodFromArray(L<PsiElement> refParts)
.fap(toCast(StringLiteralExpression.class))
.map(lit -> lit.getContents())
.fap(met -> refParts.gat(0)
.map(psi -> psi.getFirstChild())
.fap(toCast(ClassConstantReferenceImpl.class))
.flt(cst -> Objects.equals(cst.getName(), "class"))
.map(cst -> cst.getClassReference())
.fap(toCast(ClassReferenceImpl.class))
.map(clsRef -> clsRef.resolve())
.fap(toCast(PhpClass.class))
.fap(clsPsi -> resolveClass(clsPsi))
.map(cls -> cls.findMethodByName(met)));
}

Expand Down
6 changes: 6 additions & 0 deletions tests/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ private static function testGenericAccess()
}, $records);
}

private static function testArrMethRef()
{
// should suggest: "bombTransmutation", "sheerHeartAttack", "bitesZaDusto"
array_map([\DeepTest\KiraYoshikage::class, ''], [1,2,3]);
}

//============================
// not implemented follow
//============================
Expand Down

0 comments on commit 2eb6552

Please sign in to comment.