javaandroid-studiopluginsandroid-studio-plugin

How to make a simple plugin for Android Studio for custom mouse hover hint


In my java project in Android Studio I have an enum which member are used as indexes in string arrays for localization. I don't use standard Android localization tools because project is portable. I've found that it would be convenient when you move mouse over the enum value to see hint with first 50 symbols of corresponding string. Psevdocode is pretty trivial:

if classOf({word-under-mouse}) is MyStrIndEnum 
   then Hint(StringsArray[MyStrIndEnum.{word-under-mouse}.ordinal()]). 

But is it possible to write a script, plugin or something so that Android Studio do this? I never wrote addons for IDE, so please advise which way to go and is it worth to mess up with it just for convenience.


Solution

  • To do this one must write plugin using IntelliJ Idea and subclass JavaDocumentationProvider.

    Just in case someone interested:

    in build.gradle: 
    intellij {
        plugins 'java'
        plugins 'android'
        version '191.8026.42'
        type 'IC'
    }
    runIde {
        ideDirectory 'C:/Program Files/Android/Android Studio'
    }
    

    In plugin.xml:

       <extensions defaultExtensionNs="com.intellij">
               <lang.documentationProvider order="first" language="JAVA" implementationClass="smpxg.TranslationDocumentationProvider" />
        </extensions>
    

    The rest - by default.

    TranslationDocumentationProvider.java: (though isTextEnum and getTextForEnum methods specific to my case)

        public class TranslationDocumentationProvider extends JavaDocumentationProvider
        {
            @Override
            public String getQuickNavigateInfo(PsiElement element, PsiElement originalElement)
            {
                if (isTextEnum(element))
                {
                    return getTextForEnum(element);
                }
                else
                {
                    return super.getQuickNavigateInfo(element, originalElement);
                }
            }
    
    String getTextForEnum(PsiElement element)
        {
            final PsiClass base = JavaPsiFacade.getInstance(element.getProject()).findClass("smpxg.langloc.RstEng", element.getResolveScope());
            if (base != null)
            {
                String const_name = element.getText();
                String src        = base.getText();
                int    ind        = src.indexOf("ELT." + const_name);
                int    len        = ("ELT." + const_name).length();
                if (ind != -1)
                {
                    int    ind1 = src.indexOf('\n', ind + len);
                    String s    = "";
                    if (ind1 == -1)
                        s = src.substring(ind + len);
                    else
                        s = src.substring(ind + len, ind1);
                    if (s.length() > 0)
                    {
                        int from = 0;
                        for (int i = 0; i < s.length(); i++)
                        {
                            if (Character.isLetterOrDigit(s.charAt(i)))
                                break;
                            from++;
                        }
                        int to = s.length() - 1;
                        for (int i = s.length() - 1; i >= 0; i--)
                        {
                            if (Character.isLetterOrDigit(s.charAt(i)))
                                break;
                            to--;
                        }
                        if (from < to)
                        {
                            s = s.substring(from, to + 1);
                            if (s.length() > 150)
                                s = s.substring(0, 150) + "...";
                            return "<b>Eng:</b> " + s;
                        }
                    }
                }
            }
            return element.getText();
        }
    
    boolean isTextEnum(PsiElement element)
        {
            if (element != null)
            {
                ASTNode ast_node = element.getNode();
    
                if (ast_node == null)
                {
                    return false;
                }
                String element_type = ast_node.getElementType().toString();
                if (element_type.equals("ENUM_CONSTANT"))
                {
                    PsiEnumConstantImpl en = null;
                    try
                    {
                        en = (PsiEnumConstantImpl) element;
                    }
                    catch (Throwable e)
                    {
    
                    }
                    if (en != null)
                    {
                        PsiClass enum_class = en.getContainingClass();
                        if (enum_class != null)
                        {
                            String class_name = enum_class.getQualifiedName();
                            if (class_name != null && class_name.equals("smpxg.langloc.ELT"))
                                return true;
                        }
                    }
                }
            }
            return false;
        }
    }