ServiceLoader alternative for plugin SDK

Answered

I'm curious how can I create a facade class that keeps a collection of instantiated classes implementing a particular class.
So I can further filter these implementations and return specific one everwhere in the code.

Thank you.

3 comments
Comment actions Permalink

Please explain your use case and where/how you need it in your plugin.

0
Comment actions Permalink

Yann Cebron Hi!

I use PsiAugmentProvider in my plugin to generate some light elements in a class.

The provider works with built-in logic that it can return a List of generated elements of a particular type ONLY. e.g. List of fields or List of methods, but not both in one list...

I have an interface Processor:

public interface Processor {
boolean shouldProcess(PsiClass psiClass);
List<PsiField> generateFields(PsiClass psiClass);
List<PsiMethod> generateMethods(PsiClass);
}

And two implementations: Processor1 and Processor2

After that I use them in getAugments(...) looks like this:

PsiClass psiClass = (PsiClass) element;
if (type == PsiMethod.class) {
Processor1 p1 = new Processor1();
if (p1.shouldProcess(psiClass)) {
return (List<PsiMethod>) p1.generateMethods(psiClass);
}
   Processor2 p2 = new Processor2();
if (p2.shouldProcess(psiClass)) {
return (List<PsiMethod>) p2.generateMethods(psiClass);
}
}
if (type == PsiField.class) {
   Processor1 p1 = new Processor1();
if (p1.shouldProcess(psiClass)) {
return (List<PsiField>) p1.generateFields(psiClass);
}
   Processor2 p2 = new Processor2();
if (p2.shouldProcess(psiClass)) {
return (List<PsiField>) p2.generateFields(psiClass);
}
}

The problem is when new Processor is added then I need to add this scary duplications every time in my provider.

So I want this to look something like this:

PsiClass psiClass = (PsiClass) element;
List<Processor> applicableProcessors = processors.stream()
.filter(p -> p.shouldProcess(psiClass))
.collect(toList());
if (type == PsiMethod.class) {
   return (List<PsiMethod>) applicableProcessors.stream()
.flatMap(p -> p.generateMethods(psiClass).stream())
.collect(toList());
}
if (type == PsiField.class) {
  return (List<PsiMethod>) applicableProcessors.stream()
.flatMap(p -> p.generateFields(psiClass).stream())
.collect(toList());
}

Where processors is a list that is loaded with singleton instances of every existing Processor implementation.

0
Comment actions Permalink

This would be classical use-case of custom Extension Point https://plugins.jetbrains.com/docs/intellij/plugin-extension-points.html, but it probably makes no sense given you're the only consumer of this interface. Not aware of any similar "code-only" API in IntelliJ Platform.

0

Please sign in to leave a comment.