PsiSubstitutor

how to use this?
I used PsiSubstitutor.EMPTY to check wheter methods are applicable but
this simply fails. So having an expression like
method(params)
how do I collect the necessary substitutors to find the related
method?

Thanks in advance.

10 comments

Hello Sven,

SS> how to use this?
SS> I used PsiSubstitutor.EMPTY to check wheter methods are applicable
SS> but
SS> this simply fails. So having an expression like
SS> method(params)
SS> how do I collect the necessary substitutors to find the related
SS> method?

Why do you need to use the substitutor directly? Doesn't PsiCall.resolveMethod()
do what you need?

--
Dmitry Jemerov
Software Developer
JetBrains, Inc.
http://www.jetbrains.com
"Develop with pleasure!"


0

I don't have an PsiCall :(
I have an method name and the types of the parameters (and possible
their related PsiElements). Surly I am not able to create an instance
of PsiCall from it.

So I start finding the methods from known context-classes with the
related name. Then I use PsiUtil.isApplicable() for which I need
to compute the correct PsiSubstitutor.
I would be nice to have an utility method for doing it.

Dmitry Jemerov (JetBrains) schrieb:

Hello Sven,

SS> how to use this?
SS> I used PsiSubstitutor.EMPTY to check wheter methods are applicable
SS> but
SS> this simply fails. So having an expression like
SS> method(params)
SS> how do I collect the necessary substitutors to find the related
SS> method?

Why do you need to use the substitutor directly? Doesn't
PsiCall.resolveMethod() do what you need?

0

Hello Sven,

SS> I don't have an PsiCall :(
SS> I have an method name and the types of the parameters (and possible
SS> their related PsiElements). Surly I am not able to create an
SS> instance
SS> of PsiCall from it.
SS> So I start finding the methods from known context-classes with the
SS> related name. Then I use PsiUtil.isApplicable() for which I need
SS> to compute the correct PsiSubstitutor.
SS> I would be nice to have an utility method for doing it.

Do any of the methods you look for have generic type parameters? If no, PsiSubstitutor.EMPTY
should do just fine. (What exactly do you mean by "simply fails"? The source
code of PsiUtil is available, so you can see exactly what happens.)

If the methods have generic parameters, you can use PsiSubsitutor.put() to
create a substitutor instance which will perform substitutions appropriate
in your context.

--
Dmitry Jemerov
Software Developer
JetBrains, Inc.
http://www.jetbrains.com
"Develop with pleasure!"


0


A better way to find a method would be to create MethodSignature, and
findMethodBySignature() with this signature and subject class,
all the stuff resides in MethodSignatureUtil. Creating signature still
requires to pass a substitutor,
use PsiSubstitutor.EMPTY if you know all the parameter types exacly, e.g.
they either contain no references to type parameters,
or those references are already resolved (substituted) to correct type
values.

Eugene.

P.S. If you are still interested in how we obtain the substitutor for
calling PsiUtil.isApplicable(), they are taken from resolving the call
qualifier:)


"Sven Steiniger" <sven.steiniger@gmx.de> wrote in message
news:dj2m3i$45l$1@is.intellij.net...

I don't have an PsiCall :(
I have an method name and the types of the parameters (and possible
their related PsiElements). Surly I am not able to create an instance
of PsiCall from it.

>

So I start finding the methods from known context-classes with the
related name. Then I use PsiUtil.isApplicable() for which I need
to compute the correct PsiSubstitutor.
I would be nice to have an utility method for doing it.

>

Dmitry Jemerov (JetBrains) schrieb:

Hello Sven,

>

SS> how to use this?
SS> I used PsiSubstitutor.EMPTY to check wheter methods are applicable
SS> but
SS> this simply fails. So having an expression like
SS> method(params)
SS> how do I collect the necessary substitutors to find the related
SS> method?

>

Why do you need to use the substitutor directly? Doesn't
PsiCall.resolveMethod() do what you need?

>



0

The MethodSignatureUtil didn't help at all.

Finally I got most of the stuff working by carrying
the substitutor along the way.

  • For first element of an expression I use

substitutor=elementFactory.createRawSubstitutor(psiClass)

  • for going up class hierarchy I use

TypeConversionUtil.getSuperClassSubstitutor(next, current, substitutor);

  • when searching methods I use

findMethodsAndTheirSubstitutor()

Any comments on correctness?

Still I can't get methods with type parameters working.
Eq.
public ]]> X revert(X list);
is not applicable at all as there is no substituion.
Is there a utility method for this?


Eugene Vigdorchik (JetBrains) schrieb:

A better way to find a method would be to create MethodSignature, and
findMethodBySignature() with this signature and subject class,
all the stuff resides in MethodSignatureUtil. Creating signature still
requires to pass a substitutor,
use PsiSubstitutor.EMPTY if you know all the parameter types exacly, e.g.
they either contain no references to type parameters,
or those references are already resolved (substituted) to correct type
values.

Eugene.

P.S. If you are still interested in how we obtain the substitutor for
calling PsiUtil.isApplicable(), they are taken from resolving the call
qualifier:)

0

I don't know if this will help you, but here's how I find an overriding
method in a subclass in the "Abstract method with missing
implementations" inspection. This finds methods with type parameters too.

/**

  • @param method the method of which to find an override.

  • @param aClass subclass to find the methed in.

  • @return the overriding method.

*/
@Nullable
private static PsiMethod findOverridingMethod(
@NotNull PsiMethod method, @NotNull PsiClass aClass
) {
final PsiClass superClass = method.getContainingClass();
if (aClass.equals(superClass)) {
return null;
}
final PsiSubstitutor substitutor =
TypeConversionUtil.getSuperClassSubstitutor(superClass,
aClass, PsiSubstitutor.EMPTY);
final MethodSignature signature = method.getSignature(substitutor);
final List<Pair<PsiMethod, PsiSubstitutor>> pairs =
aClass.findMethodsAndTheirSubstitutorsByName(
signature.getName(), true);
for (Pair<PsiMethod, PsiSubstitutor> pair : pairs) {
final PsiMethod overridingMethod = pair.first;
final PsiSubstitutor overridingSubstitutor = pair.second;
final MethodSignature foundMethodSignature =
overridingMethod.getSignature(overridingSubstitutor);
if (MethodSignatureUtil.isSubsignature(signature,
foundMethodSignature) &&
!overridingMethod.equals(method)) {
return overridingMethod;
}
}
return null;
}

Bas

Sven Steiniger wrote:

The MethodSignatureUtil didn't help at all.

Finally I got most of the stuff working by carrying
the substitutor along the way.

  • For first element of an expression I use

substitutor=elementFactory.createRawSubstitutor(psiClass)

  • for going up class hierarchy I use

TypeConversionUtil.getSuperClassSubstitutor(next, current, substitutor);

  • when searching methods I use

findMethodsAndTheirSubstitutor()

Any comments on correctness?

Still I can't get methods with type parameters working.
Eq.
public <X extends List> X revert(X list);
is not applicable at all as there is no substituion.
Is there a utility method for this?


Eugene Vigdorchik (JetBrains) schrieb:

>> A better way to find a method would be to create MethodSignature, and
>> findMethodBySignature() with this signature and subject class,
>> all the stuff resides in MethodSignatureUtil. Creating signature still
>> requires to pass a substitutor,
>> use PsiSubstitutor.EMPTY if you know all the parameter types exacly, e.g.
>> they either contain no references to type parameters,
>> or those references are already resolved (substituted) to correct type
>> values.
>>
>> Eugene.
>>
>> P.S. If you are still interested in how we obtain the substitutor for
>> calling PsiUtil.isApplicable(), they are taken from resolving the call
>> qualifier:)

0

Thanks for the example. IG sources where the first spot I looked
for examples :)
My problem is that I don't have a method(signature). Just the
PsiClass, method name and the parameters (PsiType).
Finding candidates is not the problem. But choosing the matching
one is complicated.

Bas Leijdekkers schrieb:

I don't know if this will help you, but here's how I find an overriding
method in a subclass in the "Abstract method with missing
implementations" inspection. This finds methods with type parameters too.

/**

  • @param method the method of which to find an override.

  • @param aClass subclass to find the methed in.

  • @return the overriding method.

*/
@Nullable
private static PsiMethod findOverridingMethod(
@NotNull PsiMethod method, @NotNull PsiClass aClass
) {
final PsiClass superClass = method.getContainingClass();
if (aClass.equals(superClass)) {
return null;
}
final PsiSubstitutor substitutor =
TypeConversionUtil.getSuperClassSubstitutor(superClass,
aClass, PsiSubstitutor.EMPTY);
final MethodSignature signature = method.getSignature(substitutor);
final List<Pair<PsiMethod, PsiSubstitutor>> pairs =
aClass.findMethodsAndTheirSubstitutorsByName(
signature.getName(), true);
for (Pair<PsiMethod, PsiSubstitutor> pair : pairs) {
final PsiMethod overridingMethod = pair.first;
final PsiSubstitutor overridingSubstitutor = pair.second;
final MethodSignature foundMethodSignature =
overridingMethod.getSignature(overridingSubstitutor);
if (MethodSignatureUtil.isSubsignature(signature,
foundMethodSignature) &&
!overridingMethod.equals(method)) {
return overridingMethod;
}
}
return null;
}

Bas

Sven Steiniger wrote:

>> The MethodSignatureUtil didn't help at all.
>>
>> Finally I got most of the stuff working by carrying
>> the substitutor along the way.
>> * For first element of an expression I use
>> substitutor=elementFactory.createRawSubstitutor(psiClass)
>> * for going up class hierarchy I use
>> TypeConversionUtil.getSuperClassSubstitutor(next, current,
>> substitutor);
>> * when searching methods I use
>> findMethodsAndTheirSubstitutor()
>>
>> Any comments on correctness?
>>
>> Still I can't get methods with type parameters working.
>> Eq.
>> public X revert(X list); >> is not applicable at all as there is no substituion. >> Is there a utility method for this? >> >> >> Eugene Vigdorchik (JetBrains) schrieb: >> >>> A better way to find a method would be to create MethodSignature, and >>> findMethodBySignature() with this signature and subject class, >>> all the stuff resides in MethodSignatureUtil. Creating signature still >>> requires to pass a substitutor, >>> use PsiSubstitutor.EMPTY if you know all the parameter types exacly, >>> e.g. >>> they either contain no references to type parameters, >>> or those references are already resolved (substituted) to correct type >>> values. >>> >>> Eugene. >>> >>> P.S. If you are still interested in how we obtain the substitutor for >>> calling PsiUtil.isApplicable(), they are taken from resolving the call >>>]]> qualifier:)

0

Still struggling with methods with type parameters:
public X getFirst(List list); I have constructed a method signature (MethodSignature.toString()) getFirst(List list) and the one from IDEA looks like X getFirst(List]]> list)

Calling singature.equals() returns false. Calling
PsiUtil.isApplicable() return false.
I need a why to resolve the type-parameters according to the passed
arguments.

IDEA does this, so how can I check if a method is applicable
when resolving the type-parameters?

Sven Steiniger schrieb:

The MethodSignatureUtil didn't help at all.

Finally I got most of the stuff working by carrying
the substitutor along the way.

  • For first element of an expression I use

substitutor=elementFactory.createRawSubstitutor(psiClass)

  • for going up class hierarchy I use

TypeConversionUtil.getSuperClassSubstitutor(next, current, substitutor);

  • when searching methods I use

findMethodsAndTheirSubstitutor()

Any comments on correctness?

Still I can't get methods with type parameters working.
Eq.
public <X extends List> X revert(X list);
is not applicable at all as there is no substituion.
Is there a utility method for this?


Eugene Vigdorchik (JetBrains) schrieb:

>> A better way to find a method would be to create MethodSignature, and
>> findMethodBySignature() with this signature and subject class,
>> all the stuff resides in MethodSignatureUtil. Creating signature still
>> requires to pass a substitutor,
>> use PsiSubstitutor.EMPTY if you know all the parameter types exacly, e.g.
>> they either contain no references to type parameters,
>> or those references are already resolved (substituted) to correct type
>> values.
>>
>> Eugene.
>>
>> P.S. If you are still interested in how we obtain the substitutor for
>> calling PsiUtil.isApplicable(), they are taken from resolving the call
>> qualifier:)

0

You should look into PsiResolveHelper for calling type inference algorithm.

Eugene.

"Sven Steiniger" <sven.steiniger@gmx.de> wrote in message
news:dkn9lp$oeb$1@is.intellij.net...

Still struggling with methods with type parameters:
public <X> X getFirst(List<X> list);
I have constructed a method signature (MethodSignature.toString())
getFirst(List<Integer> list)
and the one from IDEA looks like
<X> X getFirst(List<X> list)

>

Calling singature.equals() returns false. Calling
PsiUtil.isApplicable() return false.
I need a why to resolve the type-parameters according to the passed
arguments.

>

IDEA does this, so how can I check if a method is applicable
when resolving the type-parameters?

>

Sven Steiniger schrieb:

The MethodSignatureUtil didn't help at all.

>

Finally I got most of the stuff working by carrying
the substitutor along the way.

  • For first element of an expression I use

substitutor=elementFactory.createRawSubstitutor(psiClass)

  • for going up class hierarchy I use

TypeConversionUtil.getSuperClassSubstitutor(next, current,

substitutor);

  • when searching methods I use

findMethodsAndTheirSubstitutor()

>

Any comments on correctness?

>

Still I can't get methods with type parameters working.
Eq.
public <X extends List> X revert(X list);
is not applicable at all as there is no substituion.
Is there a utility method for this?

>
>

Eugene Vigdorchik (JetBrains) schrieb:

>
>> A better way to find a method would be to create MethodSignature, and
>> findMethodBySignature() with this signature and subject class,
>> all the stuff resides in MethodSignatureUtil. Creating signature still
>> requires to pass a substitutor,
>> use PsiSubstitutor.EMPTY if you know all the parameter types exacly,

e.g.

>> they either contain no references to type parameters,
>> or those references are already resolved (substituted) to correct type
>> values.
>>
>> Eugene.
>>
>> P.S. If you are still interested in how we obtain the substitutor for
>> calling PsiUtil.isApplicable(), they are taken from resolving the call
>> qualifier:)



0

Ummh, I got it working by calling PsiSubstitutor.substitute() until
the returned value equals the argument.
So it seems this method substitutes step by step.

Sven Steiniger schrieb:

Still struggling with methods with type parameters:
public <X> X getFirst(List<X> list);
I have constructed a method signature (MethodSignature.toString())
getFirst(List<Integer> list)
and the one from IDEA looks like
<X> X getFirst(List<X> list)

Calling singature.equals() returns false. Calling
PsiUtil.isApplicable() return false.
I need a why to resolve the type-parameters according to the passed
arguments.

IDEA does this, so how can I check if a method is applicable
when resolving the type-parameters?

Sven Steiniger schrieb:

>> The MethodSignatureUtil didn't help at all.
>>
>> Finally I got most of the stuff working by carrying
>> the substitutor along the way.
>> * For first element of an expression I use
>> substitutor=elementFactory.createRawSubstitutor(psiClass)
>> * for going up class hierarchy I use
>> TypeConversionUtil.getSuperClassSubstitutor(next, current,
>> substitutor);
>> * when searching methods I use
>> findMethodsAndTheirSubstitutor()
>>
>> Any comments on correctness?
>>
>> Still I can't get methods with type parameters working.
>> Eq.
>> public X revert(X list); >> is not applicable at all as there is no substituion. >> Is there a utility method for this? >> >> >> Eugene Vigdorchik (JetBrains) schrieb: >> >>> A better way to find a method would be to create MethodSignature, and >>> findMethodBySignature() with this signature and subject class, >>> all the stuff resides in MethodSignatureUtil. Creating signature still >>> requires to pass a substitutor, >>> use PsiSubstitutor.EMPTY if you know all the parameter types exacly, >>> e.g. >>> they either contain no references to type parameters, >>> or those references are already resolved (substituted) to correct type >>> values. >>> >>> Eugene. >>> >>> P.S. If you are still interested in how we obtain the substitutor for >>> calling PsiUtil.isApplicable(), they are taken from resolving the call >>>]]> qualifier:)

0

Please sign in to leave a comment.