IntelliJ type error when using Geb static content DSL with parameters - intellij-idea

Whenever I use a static-content defined closure that takes parameters, IntelliJ will complain that the types do not match (even if I specify the type inside the closure).
For example, if I use this static content block:
static content = {
myModule { $('myModule').module(CustomModule) }
namedModule { String name -> $(".$name").module(CustomModule) }
}
Both of the above items can be used successfully in my tests, but if I was to use 'namedModule' in one of my tests as follows:
page.namedModule("moduleName").moduleMethod("blah blah blah")
IntelliJ will highlight the parameter "moduleName" in yellow with the error:
'namedModule' cannot be applied to '(java.lang.String)'
We are trying to refactor our tests in a way that means you can navigate through the code easier (e.g. avoiding any Geb/Groovy 'magic' that IntelliJ can't resolve), and this is one of the last remaining issues preventing this from being possible.

This is a known limitation to Geb support in IntelliJ. IntelliJ always treats content definitions as properties of pages and modules even though they can be parametrised. Given that Geb support in IntelliJ is open sourced we could probably add support for this.
In the mean time, as a workaround you can use methods for parametrised content instead of content definitions and IntelliJ will be able to understand these and be able to refactor them:
void namedModule(String name) {
$(".$name").module(CustomModule)
}
There are some caveats, though:
you will loose ability to use content definition options; if you need to use these for a content definition then I suggest creating a parameterised "private" content definition (for example with a _ at the beginning of the name) that you will only ever access from within the page or module
RequiredPageContentNotPresent will not be thrown even if the returned content is empty; to work around it you will either need to add manual verification to each such method or use a strategy outlined in the first bullet point with using "private" content definitions

Related

How to move a function from one Kotlin class to another using IntelliJ?

I'm using IntelliJ IDEA to refactor some Kotlin code. I have two classes in the same file and I want to move a function from one class to another using Refactor -> Move (F6), but that doesn't work, and I get tooltip message that says: "Cannot perform refactoring. Move declaration is only supported for top-level declarations and nested classes".
Am I doing something wrong? Or that refactoring is simply not supported?
[edit1] I tried to do the same operation with Java classes and everything works perfectly; so why this is not allowed for Kotlin?
[edit2] I thought that the problem is only when to two classes are in the same file, but it turns out that is not possible to move a function between classes in separate files!
It's a well-known Kotlin-only problem.
in IDEA (both free and paid editions);
in Android Studio.
Official ticket
There is an easy, but slightly janky, work around.
You just need to wrap the function you want to move in a class:
class TopLevelClass {
fun functionToMove() {
//...
}
}
wrap it in a new class
class TopLevelClass {
class TemporaryMoveClass{ /** you can now move this entire new class */
fun functionToMove() {
//...
}
}
}
and after you do the refactor, delete the temporary wrapper class you created.
The janky part is that you need to replace all instances of functionToMove() with NewTopLevelClass.functionToMove() yourself.
One of the major benefits of doing it this way, rather than just cut and pasting it yourself, is that as soon as you wrap it in the TemporaryMoveClass it will tell you any parameters you need to introduce(Refactor>Extract>Parameter). And then you can do that inside the original TopLevelClass before you move it. (this preserves the types of any TopLevelClass properties you were using, and automatically introduces the new parameter(s) into the existing function calls)

#NotNull, #Nonnull etc. all don't work in IntelliJ IDEA

I have tried annotating a field with
org.checkerframework.checker.nullness.qual.NonNull
org.jetbrains.annotations.NotNull
javax.annotation.Nonnull
And in all cases, assigning a null to it generates no complaints from IntelliJ 2016.2.
public class GreetingController {
#NotNull Integer x = 3;
public void foo() { x = null; }
}
That all compiles fine according to IntelliJ.
This page from IntelliJ specifically states that "IntelliJ IDEA highlights the problems “on-the-fly”, so you can see the inspection results right in the editor." I have even copied the example code (public class TestNullable) into my editor and it produces no errors.
This other page from IntelliJ states you can change the annotations it responds to. So I chose javax.annotation.Nonnull and made sure that was the one I was using in my code, still no luck.
To be clear, what I'm hoping for, and what I understand should be provided, is that the editor window / compiler alerts me to the problem (I am not looking for a runtime check, NullPointerException already works fine at runtime.)
In case it didn't work in real time, I tried "Rebuild Project".
I'm sure this must work, what am I doing wrong?
I have uploaded an example of this not working here: ZIP download.
As I can see from your screenshots and the sample project, IntelliJ IDEA does show you the warnings. Note that these warnings are shown by the code inspections which are running on the fly and will be displayed in the editor or in the Analyze | Inspect Code results. These warnings will not be displayed by the compiler.
Note that you can configure the warnings highlighting if needed (for example add the underwave effect):
You can also change the severity of the inspection (like to Error):
You may also want to vote for this feature request:
IDEA-78625 Provide inspection severity level that will work like validation and abort compilation
As a bonus, pay attention to the javax.annotation.Nullable annotation, it may be not what you think it's for, see this comment and the documentation. For some years IntelliJ IDEA has incorrectly suggested to use this annotation, while the correct one for such cases would be javax.annotation.CheckForNull:
This annotation is useful mostly for overriding a Nonnull annotation.
Static analysis tools should generally treat the annotated items as
though they had no annotation, unless they are configured to minimize
false negatives. Use CheckForNull to indicate that the element value
should always be checked for a null value.
"Settings" > "Inspections" > "Probable Bugs" > "Constant conditions & exceptions"
Tick the first option: "Suggest #NotNull annotation for methods that possibly return null and report nullable values passed to non-annotated parameters.
Click "Configure Annotations". By default, Intellij will use their own annotations from org.jetbrains.annotation. I was using the more general (my own opinion) annotations from javax.annotation.
I set Nullable to: javax.annotation.Nullable
I set NotNUll to : javax.annotation.NotNull
In order to set these new options, you must click them, then click the tiny checkmark button to the right to set it. Selecting the javax.annotation annotations then hitting "OK" will NOT lock in the new settings, you must use the checkbox button.
After successfully specifying javax.annotation.Nullable and javax.annotation.NotNull, the code correctly highlighted null problems.
The best that this can do is offer up warnings. It will not stop compilation from happening, since the annotations do not prohibit or preclude code compilation from taking place.
Be sure that you have the appropriate inspections enabled in your IDE, and be sure that you remain aware of what parameters you're passing into your method. The IDE can at best warn you, but it can't really stop you.
Alternatively, introduce a unit test to fail if that method receives a null parameter, and rely on that to ensure that you're not breaking code or expectations.

switching between languages in same file

I recently attended a user group meeting where the IntelliJ representative was demonstrating version 13.
He demonstrated how to switch the code completion view of a file. I do not exactly remember what the file extension of this particular file was, probably java.
The concept was that if the file is html with embedded javascript he could then switch the code completion between html and javascript with a shortcut. If he says treat the file as html then all code in file was treated for code completion purposes as html, and vice versa for javascript.
Does anybody know what shortcut he might have been using to enable the language switch?
Sounds like you may be referring to the IntelliLang feature. IntelliJ IDEA can be aware of other languages embedded within a file.
A simple example is in an HTML file that has CSS and JavaScript.
Notice when I am inside the HTML markup:
or inside an HTML element:
The code complete shows HTML completion options. However, when I am inside the style attribute, I get CSS code completion:
I also get CSS code completion if I am inside a <style> element. So even though I am in an HTML file, I see CSS code completion because of my location.
Same case with JavaScript. When I invoke code completion inside a <script> element, I get JavaScript completion, even though I am in an HTML file.
Anytime IntelliJ IDEA can determine that another embedded language is present, it provides, via IntelliLang, the appropriate syntax highlighting, error highlighting, and code completion. The same holds true for Java. Notice here that IDEA knows the method I am competing takes an SQL statement and therefore highlights the String value using SQL highlighting, and provides SQL code completion:
So even though I am in a .java file, I get SQL code completion. The reason is that IntelliLang comes pre-configured knowing the embedded language of some methods. You modify them, or add more, in File > Settings > [Project Settings] > Language Injections.
In addition, you can use an annotation to tell IntelliJ IDEA (as well as developers looking at the code) that a String must be valid in a particular language. For example, I can annotate a String field, variable, or parameter, to indicate it must be valid HTML:
Notice I get HTML syntax highlighting, HTML code completions, and the CSS color shows in the left gutter. If I annotate a method parameter, then any time I call the method, I get the appropriate syntax highlighting, code completion, and error/warning highlighting:
The #Language annotation is inside the annotations.jar that is contained in the redist directory inside the IntelliJ IDEA installation directory. It is also available in maven central, or IDEA will offer to attach it as a Library if you use the annotation without it being attached.
IntelliLang and the #Language annotation supports a large number of languages. Just use code Completion inside the quotes after typing #Language("") to see a list. (Inline search works in the list as well.) One of the most useful is Regexp. For example, if you have a method that expects the string passed in to be a valid Regular Expression, annotating it as such will give anyone that calls it Regex code completion and error highlighting if they are passing in an invalid Regex pattern. Even for developers using other IDEs it is useful as a form of documentation.
As for a shortcut to change the the language on the fly for code completion, the only thing I can think that you might be referring to is the "Inject Language" intention. If I am entering a String value, and I bring up the quick-fix/intention menu via Alt+Enter, I am given an option to inject a language:
If I select that, IntelliJ IDEA will ask me what language I want to use:
After making my selection, IntelliJ IDEA will give me temporary language injection (including code completion) for the selected language.
It also gives me an option to add the #Language annotation for permanent injection.
To the best of my knowledge (as a 10 year IntelliJ IDEA user) that is the only way to switch code completion language types. So hopefully that is what you are looking for. To me, IntelliLang is one of the coolest features in IntelliJ. (It actually started as a third party plug-in and JetBrains then absorbed it into the product.)

Eclipse custom text editor update syntax highlighting

I am writing an Eclipse plugin (Indigo/Juno) that contains a text editor for a custom text format. I am following the tutorial here: http://www.realsolve.co.uk/site/tech/jface-text.php
So far I have everything working. Eclipse will use my editor to edit files. I have partitioning, damaging, repairing, syntax highlighting all working.
I added a preferences page with color pickers to control syntax highlighting. It works mostly correct. If I update the colors, the editor uses them the next time I open or reopen a file.
How do I get an editor tab to update itself without opening a new one? The built-in JDT Java editor does this, but so far I have not been able to decipher how (it is a very large and complex editor).
I gather that I need to create a preferences listener (http://www.vogella.com/articles/EclipsePreferences/article.html). I have done this and can verify that my listener code is being invoked when I set a breakpoint in it.
The missing piece is the wiring between the listener and reinitializing the editor. I have tried reconstructing the partitioning logic, the color logic, the damager/repairer, etc. but nothing seems to work. It either does nothing I can see or at worst will corrupt the display until I scroll the current text out of view to repaint it... with the old colors.
Any ideas?
I think SourceViewer.invalidatePresentation() needs to be called.
It may be already late to you, but if you want you could use LiClipse for that (http://brainwy.github.io/liclipse/) -- one of its targets is easily doing an editor with syntax highlighting, basic code-completion, outline, etc targeting Eclipse.
No java skills are required to add a new language (mostly creating a new .liclipse -- which is a YAML -- file in the proper place and creating some basic rules to say how to partition your language -- i.e.: usually just separating code from comments from strings -- and specifying the keywords you have in the partition would already give you proper syntax highlighting).
If you download it, there are a number of examples at plugins\com.brainwy.liclipse.editor\languages and there's some basic documentation at http://brainwy.github.io/liclipse/supported_languages.html and http://brainwy.github.io/liclipse/scope_definition.html on how to do it.
For anyone coming across this as I did:
My solution involved adding the following lines into the Constructor of my Editor
Activator.getActivator().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent event) {
getSourceViewer().invalidateTextPresentation();
handlePreferenceStoreChanged(event);
}
});
and then creating a custom class that extended IToken. In the constructor I pass the String of the preference field and then in the 'getObject' method I create the TextAttribute: snippets below
public class MyToken extends Token implements IToken {
public MyToken(Object data) {
super(data);
}
#Override
public Object getData() {
String dataString = (String) super.getData();
return getAttributeFromColorName(dataString);
}
private TextAttribute getAttributeFromColorName(String preferenceField) {
Color color = new Color(Display.getCurrent(), StringConverter.asRGB(Activator.getActivator().getPreferenceStore().getString(preferenceField)));
return new TextAttribute(color);
}
}
When I generate my Rules I have all of my tokens as my custom class and this allowed me to change syntax color dynamically.
I also added an example for updating the coloring if the preference changes to https://www.vogella.com/tutorials/EclipseEditors/article.html#exercise-allow-user-to-customize-the-colors
This is using the Generic editor (currently the best approach to implement a customer editor) but it should be possible to adjust this to any Eclipse editor implementation.

Weird JavaCore IType cache problem

I'm developing a plugin that takes all enums in workspace that implements certain interface (IDomain) parses the code (Using AST) does some modification over the enum and marks it as processed with an annotation (#IDomainInfo).
For example, it takes someting like this:
public
enum SomeEnum implements IDomain {
// ...
}
And generates something like this:
public #IDomainInfo(domainId = 1)
enum SomeEnum implements IDomain {
// Some changes here...
}
The idea behind of the #IDomainInfo is that annotated enums have not to be processed anymore by the plugin.
Basically what I do to accomplish the task is to make a search with JavaSearch API to find all the enums implementing IDomain (easy task), and as result I get a list of IJavaElements (which are in fact instances of IType). Then I call a method that iterates through the resulting list and creates a new list of all the IType instances that are not annotated with #IDomainInfo and then process the resulting list: For each non annotated IType do some work, annotate the IType with the #IDomainInfo annotation (Using AST) and then save back the results to file (using IFile, so I can see the changes without refresh, and in fact, if I have the enum open in the editor I see it refreshed instantly :-)
All that works fine, but if I open an #IDomainInfo annotated enum (just for testing) then remove the #IDomainInfo, save the file (I'm sure) and then call the action that does all the job I've described before, when I get to the part that filters annotated IType from non annotated ones, code is something like this:
for (IType type : typeList) {
IAnnotation annotation = type.getAnnotation(“IDomainInfo”);
if (!annotation.exists()) {
// The annotation does not exist, so add the type to the
// list of elements to update and go on...
ret.add(type);
continue;
}
// Something else here...
}
Well, it results that for the file I've just saved the IType detects the annotation I've just removed as if it's still there. If I close and reopen eclipse all works normally.
Now, I've just checked and triple checked my code, so I'm sure that I'm not keeping a stale copy of the old IType unedited still with the annotation version (all my IType come from a fresh java search call every time I run the action).
So the question is, what might I be doing wrong? I mean, I've just read the JavaCore API many times to check If I might be using it wrong or if I have some conceptual flaw there but really I have no clue, it's like if eclipse would be caching the IType ignoring the changes I've just made in the editor :-/
If any one have an idea I would appreciate it a lot :-)
When or how is your plugin called ? Did you register a resource listener or is it a project builder or something else ? If it is called by a resource listener, your plugin may be reading the 'primary copy' for your IType, which has not been saved yet. Hence your changes are still in the Working Copy.