Find reference to java method

Hi guys,

The situation is following:


The reference to Java method "getName" is contained both "person.getName" and "person.name"
But when I run "Find usages" action the Java method I get only "person.getName" usage.
The reference from "person.name" isn't even taken during search.
I know that this happens due to the inequality of token, but I'm not sure how it can be solved.

Would be grateful for any help

3 comments

I found in my plugin that for Find Usages the IDE will do a text search on the index and if a file contains a matching text reference, then it will be parsed and searched. So if a reference does not textually match then it is not found.

The solution I found is to add an alternate text to the reference search and add the class to the plugin extensions.

<extensions defaultExtensionNs="com.intellij">
    <referencesSearch implementation="com.vladsch.markdown.MarkdownReferenceSearch"/>
</extensions>

I am not sure if your issue is exactly the same as I encountered but it does appear to have the same roots so you can try this solution.

Note that this class is an example that I created from my class which is in Kotlin and handles markdown specific stuff. So you will need to validate and debug the meat of it that adds alternate(s) to the string array.

package com.vladsch.markdown;

import com.intellij.openapi.application.QueryExecutorBase;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiReference;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;

import static java.lang.Character.isUpperCase;

class MarkdownReferenceSearch extends QueryExecutorBase<PsiReference, ReferencesSearch.SearchParameters> {
    public MarkdownReferenceSearch(final boolean requireReadAction) {
        super(true);
    }

    @Override
    public void processQuery(@NotNull final ReferencesSearch.SearchParameters queryParameters, @NotNull final Processor<PsiReference> consumer) {
        final PsiElement elementToSearch = queryParameters.getElementToSearch();
        final SearchScope effectiveSearchScope = queryParameters.getEffectiveSearchScope();
        boolean isCaseSensitive = elementToSearch.getLanguage().isCaseSensitive();

        // here you need to examine the elementToSearch and add any textual references
        // which do not equal the element name as recognized by the IDE
        // debug and validate this part
        if (elementToSearch instanceof PsiMethod) {
            String name = ((PsiMethod) elementToSearch).getName();
            if (name.startsWith("get") && name.length() > 3 && isUpperCase(name.charAt(3))) {
                String altName = name.substring(3, 4).toLowerCase() + name.substring(4);
                queryParameters.getOptimizer().searchWord(altName, effectiveSearchScope, isCaseSensitive, elementToSearch);
            }
        }
    }
}
0

Hello Vladimir Schneider,

Many thanks for your answer.
I've been into debug of Intellij for few hours already and found an interesting thing:

The class com.intellij.psi.impl.search.MethodUsagesSearcher

Has following call:

SimpleAccessorReferenceSearcher.addPropertyAccessUsages(method, restrictedByAccessScope, collector);
>

static void addPropertyAccessUsages(PsiMethod method, SearchScope scope, SearchRequestCollector collector) {
final String propertyName = PropertyUtil.getPropertyName(method);
if (StringUtil.isNotEmpty(propertyName)) {
SearchScope additional = GlobalSearchScope.EMPTY_SCOPE;
for (CustomPropertyScopeProvider provider : Extensions.getExtensions(CustomPropertyScopeProvider.EP_NAME)) {
additional = additional.union(provider.getScope(method.getProject()));
}
final SearchScope propScope = scope.intersectWith(method.getUseScope()).intersectWith(additional);
collector.searchWord(propertyName, propScope, UsageSearchContext.IN_FOREIGN_LANGUAGES, true, method);
}
}

Please notice the

final String propertyName = PropertyUtil.getPropertyName(method);

It comes out Idea already makes this alternative property name thing inside:

@Nullable
public static String getPropertyName(@NotNull PsiMethod method) {
if (isSimplePropertyGetter(method)) {
return getPropertyNameByGetter(method);
}
if (isSimplePropertySetter(method)) {
return getPropertyNameBySetter(method);
}
return null;
}

@NotNull
public static String getPropertyNameByGetter(PsiMethod getterMethod) {
@NonNls String methodName = getterMethod.getName();
return methodName.startsWith("get") ?
StringUtil.decapitalize(methodName.substring(3)) :
StringUtil.decapitalize(methodName.substring(2));
}

In "addPropertyAccessUsages" method the CustomPropertyScopeProvider.EP_NAME extension uses which enables you to specify custom search scope for these "alternative" properties.

I've tried it following way:

plugin.xml:

<customPropertyScopeProvider implementation="com.aemtools.findusages.HtlPropertyScopeProvider"/>

The class

class HtlPropertyScopeProvider : CustomPropertyScopeProvider {
override fun getScope(project: Project): SearchScope =
GlobalSearchScope.getScopeRestrictedByFileTypes(
GlobalSearchScope.allScope(project),
StdFileTypes.HTML)
}

And it worked out just perfect:


:-)

But I don't have any confidence whether this approach is good or not. 

0

Dmytro Troynikov, I cannot see your last comment that I received by e-mail as a post here.

Your solution makes better sense than the solution I gave in the example. If it works then until you find otherwise assume that it is correct.

I am willing to venture that under the hood it does something similar to the text search modification.

In my case the text differences involved non-standard IDE handling like spaces or dashes in file names matching: spaces, dashes, pluses, slashes, etc in link references. I too spent hours in the debugger to figure out what was going on and how to make it work.

 

 

0

Please sign in to leave a comment.