Efficient way to get configuration elements for a specific plugin in Eclipse RCP - eclipse-plugin

I want to find all extensions of org.example.extension.point declared in com.example.plugin. Is there a more efficient way to do so than doing
List<IConfigurationElement> result = new ArrayList<IConfigurationElement>();
IConfigurationElement[] allConfigElements =
Platform.getExtensionRegistry.getConfigurationElementsFor("org.example.extension.point");
for (IConfigurationElement ice : allConfigElements) {
if (ice.getDeclaringExtension().getNamespaceIdentifier() == "com.example.plugin")
result.add(ice);
}
return result;
?

No there are no other (more efficient) ways (is this not simple enough?;). In addition I'd use ice.getContributor().getName() instead of ice.getDeclaringExtension().getNamespaceIdentifier()
I really would like to know why you want to filter by a specific contributor. - I mean if you have to "know" the contributor why are you using the extension point? The main purpose of an extension point is using inversion of control; the main characteristic of using extension points is not knowing the contributor. No offense, but probably you are using extension points in a way they are not intended for...

Related

how do I write Intellij plugin to display python class methods return value from static analysis (for very simple expressions)?

I would like to write Intellij plugin that can display values returned by class def() in python. I would like those values to be evaluated as much as possible and done by static analysis. I need this to work only for very simple expressions in one particular use case.
We have class definitions in our python code base that consist of a lot of very simple def()s.
All the defs are just one return statement returning very simple expression.
All of the code follows the same pattern and uses very few python operator.
the code is long and really hard to follow.
After few jumps "to definition" within this class I can't remember where I am anymore.
I am hoping that some intellij plugin can lessen the pain.
So for example. this is short and very simplified code fragment. hopefully it will be enough to demonstrate the problem.
class SomeClass(object):
def __init__(self, param):
self.param = param
def a(self):
return self.param + 1
def b(self):
return self.a + otherfunc()
def c(self):
return self.b + 3
I would like the plugin to display the following:
class SomeClass(object):
def __init__(self, param):
self.param = param
def a(self): # = param + 1
return self.param + 1
def b(self): # = param + 1 + otherfunc()
return self.a + otherfunc()
def c(self): # = param + 1 + otherfunc() + 3
return self.b + 3
This is just an illustration, real code makes more sense. but the expressions themselves are that simple.
Comments represent plugin output. I would like those values to be always visible as code hints, tooltips or whatever. and be updated as I type.
I don't want to evaluate the defs, because some of the values are not available before runtime. I want to get the expression itself from AST.
Obviously this is impossible to do in the general case. But I have a very specific use case in our code base
where very small python subset is used. And all the code follows the same pattern.
I already have a script that does this in python with ast module. I wonder if there is a way to do the same on the fly in Intellij.
Is there some way to achieve this? or something similar?
Is there a plugin that does something like that?
I doubt that there is. at least not exactly. So I want to try to implement it myself. (the use case is common and very annoying).
I skimmed through some of Intellij Platform Plugin SDK documentation. it's still not clear to me where to begin.
So what would be the easiest way to implement it from scratch or using another plugin as an example?
Is there an opensource plugin that does something similar that I can look at to figure out how to implement this myself?
My best guess is that I would need to implement:
create a call back that will be called every time def() is changed. (by implementing various extensions, no? which one?)
find this def in the file.
walk expression with PSI to extract the expression
create some GUI element to represent the def expression. (what are my options? is there some predefined elements that I can use?
ideally I would assign value to some existing GUI element)
assign value to the GUI element
but I don't know how to begin implementing any of the above. (I can probably figure out PSI part)
I searched for existing plugins, but couldn't find anything even remotely close. I skimmed the documentation, I did the tutorial, but I couldn't figure out which of the many extensions I need to use.
I considered using the debugger for that, but I don't see how debugger can help me here.
Any help (plugins, tutorials, extensions, plugins as an example, or details for implementation) would be greatly appreciated. thanks.
What you want to find is some extension point that will change the text user sees. I suggest you to look at the annotator class but maybe this is not the best extension point for you and you will need to find more suitable one (this is the most difficult part of creating plugins for JetBrain's IDEs). Full list of all available extension points you can find here.
After you find right extension point you need to implement it and change plugin.xml to let IDE know that some changes were made.
Some useful links:
Example plugins from developers
Official documentation
Quick course from JetBrain's developer (in Russian)

Mono.Defer() vs Mono.create() vs Mono.just()?

Could someone help me to understand the difference between:
Mono.defer()
Mono.create()
Mono.just()
How to use it properly?
Mono.just(value) is the most primitive - once you have a value you can wrap it into a Mono and subscribers down the line will get it.
Mono.defer(monoSupplier) lets you provide the whole expression that supplies the resulting Mono instance. The evaluation of this expression is deferred until somebody subscribes. Inside of this expression you can additionally use control structures like Mono.error(throwable) to signal an error condition (you cannot do this with Mono.just).
Mono.create(monoSinkConsumer) is the most advanced method that gives you the full control over the emitted values. Instead of the need to return Mono instance from the callback (as in Mono.defer), you get control over the MonoSink<T> that lets you emit values through MonoSink.success(), MonoSink.success(value), MonoSink.error(throwable) methods.
Reactor documentation contains a few good examples of possible Mono.create use cases: link to doc.
The general advice is to use the least powerful abstraction to do the job: Mono.just -> Mono.defer -> Mono.create.
Although in general I agree with (and praise) #IlyaZinkovich's answer, I would be careful with the advice
The general advice is to use the least powerful abstraction to do the job: Mono.just -> Mono.defer -> Mono.create.
In the reactive approach, especially if we are beginners, it's very easy to overlook which the "least powerful abstraction" actually is. I am not saying anything else than #IlyaZinkovich, just depicting one detailed aspect.
Here is one specific use case where the more powerful abstraction Mono.defer() is preferable over Mono.just() but which might not be visible at the first glance.
See also:
https://stackoverflow.com/a/54412779/2886891
https://stackoverflow.com/a/57877616/2886891
We use switchIfEmpty() as a subscription-time branching:
// First ask provider1
provider1.provide1(someData)
// If provider1 did not provide the result, ask the fallback provider provider2
.switchIfEmpty(provider2.provide2(someData))
public Mono<MyResponse> provide2(MyRequest someData) {
// The Mono assembly is needed only in some corner cases
// but in fact it is always happening
return Mono.just(someData)
// expensive data processing which might even fail in the assemble time
.map(...)
.map(...)
...
}
provider2.provide2() accepts someData only when provider1.provide1() does not return any result, and/or the method assembly of the Mono returned by provider2.provide2() is expensive and even fails when called on wrong data.
It this case defer() is preferable, even if it might not be obvious at the first glance:
provider1.provide1(someData)
// ONLY IF provider1 did not provide the result, assemble another Mono with provider2.provide()
.switchIfEmpty(Mono.defer(() -> provider2.provide2(someData)))

How to prevent empty list errors in in clause in sql?

One common problem we have in our codebase is that people forget to check if a list is empty before using it in an in clause.
For example (in Scala with Anorm):
def exists(element: String, list: List[String]): Boolean =
SQL("select {element} in {list} as result")
.on('element -> element, 'list -> list)
.as(SqlParser.bool("result").single)
This code works perfectly well as long as list has at least one element.
If it has 0 elements, you get a syntax error, which is weird if you're used to other programming languages that would allow this empty list case.
So, my question is: what's the best way to prevent this error from happening?
Initially, we did this:
def exists(element: String, list: List[String]): Boolean =
if (list.nonEmpty) {
SQL("select {element} in {list} as result")
.on('element -> element, 'list -> list)
.as(SqlParser.bool("result").single)
} else {
false
}
This works perfectly well, and has the added advantage that it doesn't hit the database at all.
Unfortunately, we don't remember to do this every time, and it seems that 1-2 times a month we're fixing an issue related to this.
An alternate solution we came up with was to use a NonEmptyList class instead of a standard List. This class must have at least one element. This works excellent, but again, people have not been diligent with always using this class.
So I'm wondering if there's an approach I'm missing that prevent this type of error better?
It looks like you've already found a way to resolve this problem - you have an exists() function which handles an empty list cleanly. The problem is that people are writing their own exists() functions which don't do that.
You need to make sure that your function is accessible as a utility function, so that you can reuse it whenever you need to, rather than having to rewrite the function.
Your problem is an encapsulation problem: the Anorm API is like an open flame and people can burn themselves. If you rely just on people to take precautions, someone will get burnt.
The solution is to restrict the access to the Anorm API to a limited module/package/area of your code:
Anorm API will be private and accessible only from very few places, where it is going to be easy to perform the necessary controls. This part of the code will expose an API
Every other part of the code will need to go through that API, effectively using Anorm in the "safe" way

(How) can a VS Code extension access [language]-specific `settings.json` sub-section values?

Example: extension code can very trivially determine the value of editor.formatOnSave. But from what I can tell and have tried, it seems nigh impossible to query the current document/editor whether that setting is effective right there, right now. With [language]-specific sub-sections it may be enabled for Go but disabled for others for example --- or vice versa. And "some" (ie. mine) extension might "need" (ie. want) to know about it!
If you try to use the documented getConfiguration("language").get("setting") it won't work. But there is a workaround to access what you want.
Let's suppose you want to load editor.formatOnSave for markdown files. If you look at User Settings, you will see it stored like this:
["markdown"]: {
"editor.wordWrap": "wordWrapColumn",
"editor.formatOnSave": true
}
You just have to load the configuration object and access the desired properties, like this:
let markdownObject = vscode.workspace.getConfiguration("[markdown]");
if (markdownObject["editor.formatOnSave"]) {
console.log("[markdown].editor.formatOnSave is TRUE");
}
It's important to note that you must use [markdown] (between brackets) because that is how it is represented on the JSON file.
Also note that this workaround will not give you access to settings that are not overridden for languages. In that case, you must use/combine the documented API.

Math Parser/Lexer - Token interface design

Currently working on a small pet project, a Math Parser/Lexer and eventually solver for fun/learning. I've bashed out a basic prototype and am now looking to convert this into TypeScript to clean things up. Prototype can be found here https://github.com/chips5k/math-solver-prototype for those interested.
I am trying to come up with a clean interface based approach to dealing with my Tokens. I suspect i am looking at this the wrong way, but hopefully someone can offer useful advice.
In my TS design i have several interfaces, the base interface being Token, with NumericToken and FunctionToken extending these. I then have several classes that implement these interfaces such as: AdditionToken, VariableToken, NumberToken, PiToken, SineToken etc...
My problem is that in order to work with these interfaces i end up requiring methods to check the basic type e.g isNumeric, isFunction, isVariable or alternatively a direct type === TokenFactory.NUMERIC etc... This, to me, feels wrong as it basically voids the point of using an interface. I suspect that there is a nicer/cleaner more polymorphic approach i could take but unfortunately i'm out of ideas and have been unable to find info on what i am doing.
An example of where things fall apart shows itself when attempting to solve a series of tokens:
if(t.isFunction()) {
var a = stack.unshift();
var b = stack.unshift();
if(a.isNumeric() && b.isNumeric()){
result.push(tokenFactory.create(t.evaluate<number>(a.evaluate<number>, b.evaluate<number>));
} else {
//return to stack and move on, e.g can't solve x + 1 directly
}
} else {
stack.push(t);
}
Basically looking for what is considered the ideal approach for handling a scenario like this, and i suspect it may be an alternate approach to the design.
TIA!
basic type e.g isNumeric, isFunction, isVariable or alternatively a direct type === TokenFactory.NUMERIC etc... This, to me, feels wrong
Nope. This is fairly idiomatic as the type controls what functionality is there.
E.g you will see the TypeScript checker.ts littered with check on .kind (SyntaxKind) which is at TypeScript AST nodes discriminator.
Also you might want to consider adding a visitor that is recursive e.g.
function visit(item){
if (item.addition) {
return visit(item.left) + visit(item.right)
}
if (item.literal) {
return literal.value();
}
// ETC.
}