Code Completion - get context in which is method called
Hi,
I am developing plugin for code completion in PHP method parameters. I have following code:
public class OptionsCompletionContributor extends CompletionContributor {
@Override
public void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) {
PsiElement element = parameters.getPosition().getParent();
ParameterList parameterList = PsiTreeUtil.getParentOfType(element, ParameterList.class);
if (parameterList == null) {
return;
}
PsiElement[] givenParameters = parameterList.getParameters();
PsiElement context = parameterList.getContext();
if(context instanceof MethodReference){
MethodReference method = (MethodReference) context;
ClassReference cls = (ClassReference) method.getClassReference();
// here I need help
}
}
}
So I know method and class for example here:
<?php
}
class SomeClass {
public static function someMethod($someParameter){
}
public static function someMethod2($someParameter){
}
public static function iDontCareAboutThisMethod($someParameter){
}
I know it´s class "SomeClass", method "someMethod" or "someMethod2" and I know it´s first parameter as well. I am doing code completion for $someParameter in these methods.
But now what I need:
<?php
class Test {
public function something(){
SomeClass::someMethod("foo");
SomeClass::iDontCareAboutThisMethod("something");
SomeClass::someMethod2("bar");
SomeClass::someMethod(/* here is my cursor and here and want code completion "foo" and "bar"*/);
}
}
I need to know that I am in some method called "something" and I need to get all calls of "someMethod" and "someMethod2" methods and their parameters. So in this case I want to get List of "foo" and "bar".
Is there any possibility to do this?
Thanks for help!
请先登录再写评论。
are you looking for parameters passed to someMethod / someMethod2
in the context of one function (in this example, function something())
?
Yes, this is exactly what I need.
assuming that your Psi Tree looks something like this:
CLASS
FUNCTION
SYMCL :: SYMMETHOD (PARAM*)
you could walk up & down Psi Tree
completion parameters -> PsiElement ->
up to FUNCTION -> collect SYMMETHOD[] -> filter by name -> PARAM[]
does this makes any sense ?
I understand the principle but I don´t know how can I do it.
I have instance of CompletionParameters called parameters. I have Psi Element: PsiElement element = parameters.getPosition().getParent(); (is this right?)
But now I have no idea how to continue. How can I get instance of Function?
this seems ok:
PsiElement element = parameters.getPosition().getParent();
now you can call element.getParent().getParent()... until you get up to Function PsiElement
then you could call PsiTreeUtil.collectElements(functionElement, PsiElementFilter) to find methods down in the tree.
from each method you could call PsiTreeUtil.collectElements(methodElement, PsiElementFilter) to find parameters.
then on each parameter call getText(), put them in a Set<String>, and once this set is ready, you could call this:
Thank you for your help, now I have last problem :)
My code:
I cannot get class reference because of following exception:
ClassCastException: com.jetbrains.php.lang.psi.elements.impl.MethodReferenceImpl cannot be cast to com.jetbrains.php.lang.psi.elements.ClassReference
Which way can I get reference to class? According to my first post I need to check that "someMethod" or "someMethod2" is only from "SomeClass".
to prevent the cast error, before casting an element, you could check its type first:
element instance of XSYMMETHOD
or (element.class.isAssignableFrom(XSYMMETHOD.class)
|| XSYMMETHOD.class.isAssignableFrom(element.class))
text of any PsiElement e.g. "someMethod" is PsiElement.getText()
to collect PsiElements of some class / IElementType but not other, tweak PsiElementFilter like this:
boolean isAccepted(PsiElement element){
return element instance of XSYMMETHOD
// or
return el.getNode().getElementType().equals(XTypes.SYMMETHOD);
}
you could also create a TokenSet tokenSet by TokenSet.create(...)
and check it by tokenSet.contains(IElementType)
Thank you very much for your help!
My final working solution is test getText() method on PsiElement which represents method.
:)
you are welcome