How to get access from ToolWindowFactory based class to current source code - intellij-idea

Ian writing a inspection Plugin for IntelliJ. For this Plugin I need access from ToolWindowFactory based class to current source code (cursor position etc.). Theres a way across the PSIManager, but only in AnAction derived classes, not for ToolWindowFactory derived classes. There are any Ideas?

Perhaps a com.intellij.openapi.editor.event.CaretListener would work? You can register it as follows to receive events for all open editors.
com.intellij.openapi.editor.EditorFactory.getInstance().getEventMulticaster().addCaretListener(myCaretListener);

CaretListener listener = new CaretAdapter() {
#Override
public void caretPositionChanged(CaretEvent e) {
System.out.println(e.getNewPosition());
}
};
com.intellij.openapi.editor.EditorFactory.getInstance().getEventMulticaster().addCaretListener(listener);

Related

How to create a BaseClass that adds logging messages

I am using serenity BDD for my automation testing and Page Object Model for my framework. I have created a BasePage class which will be inherited by all the other Pages. I want to minimize the logging messages from the Pages by adding all the log.info messages to a central Base page. Example, when calling the click() method, I will log before click and after click methods as shown below in the basePage class:
public class BasePage extends PageObject{
private static final Logger log = LogManager.getLogger(BasePage.class.getClass());
private final WebElementFacade element;
public static void clickBtn(WebElementFacade btnName) {
log.info("About to click " + btnName + " button");
btnName.click();
log.info("Successfully clicked on " + btnName + " button.");
}
Later I figured that instead of individually trying to figure out in advance what actions the user will perform on the webElements, and write new methods for each action (like the one shown above), just implement WebDriverFacade interface, so that I get all the unimplemented method list in BasePage from WebDriverFacade and then write the log messages inside each of them, like so:
public class BasePage extends PageObject implements WebElementFacade{
private static final Logger log = LogManager.getLogger(BasePage.class.getClass());
private final WebElementFacade element;
#Override
public void submit() {
// TODO Auto-generated method stub
}
#Override
public void sendKeys(CharSequence... keysToSend) {
// TODO Auto-generated method stub
}
#Override
public String getTagName() {
// TODO Auto-generated method stub
return null;
}
#Override
public boolean isSelected() {
// TODO Auto-generated method stub
return false;
}
.
.
.
.
.
}
This will serve two purposes:
I will not have to create new methods for every action in BasePage class, example the 'clickBtn()' function in the first code
As I mentioned before, I will not have to figure out what method any other person who adds methods to my code might use and having to change the BasePage class to create the new actions. So basically less maintenance in the long run.
The problem I am facing is an error that I receive in the second use case:
The return types are incompatible for the inherited methods WebElementFacade.withTimeoutOf(int, TimeUnit), PageObject.withTimeoutOf(int, TimeUnit)
Now my question is:
How can solve this problem?
Is this the right way to do things or should I be going with the first method and have maintenance overhead.
Just figured that another scenario where this might be useful. To make sure that subclass methods do not use methods from pageObject and are forced to use the methods from BaseClass only. This can be done by wrapping the WebElementFacade and adding the log messages as an added functionality. Any thought on this would be appreciated.
Thank you!
Honestly it is a neat trick and if you get it working you should be proud.
I think I figured something similar out in a dynamic language.
But you are better off just adding the logging entries and learning the following.
How to name functions so you don't feel like they need renaming.
How to log clearly for debugging use.
This is because loggings power is in its flexibility.
When you learn how to dump something complex like a matrix so you can eye it and go uh-oh you are increasing your overall skills.
I apologize for not giving you code but I felt some "chase the other rabbit" advice was better.

How to access test method annotations from a TestExecutionListener

I'm trying to port Test Management For Jira JUnit Integration to JUnit5. This module generates a JSON report of the test run and associates the results with Jira tickets by using annotations on the test methods, example.
From the TestExecutionListener I'm not sure what the best approach to retrieve the TestCase annotation is.
I looked at Reflection using the TestIdentifier.getSource and doing manipulations to rebuild the method signature and extracting the annotation from there but the approach felt clumsy.
I came across this post Allow extensions to register TestExecutionListeners which proposed the following:
Proposal: Have your extension publish the WebDriver bean's session id, e.g.
String sessionId = ...;
extensionContext.publishReportEntry("webDriverSessionId", sessionId)
In your TestExecutionListener, implement reportingEntryPublished and store it in a Map with the TestIdentifier as a key. In executionFinished report the test outcome along with the value from this Map.
This approach looks promising but I want to make sure there isn't another way that doesn't require both an extension and a test execution listener. Is there a way to retrieve test method annotation information directly in the TestExecutionListener?
#Alex, the following might be used inside the listener...
((MethodSource) testIdentifier.source).javaMethod.getAnnotation(TestCase.class)
Seems like you can't get test annotation from TestExecutionListener but instead you can implement TestWatcher or e.g AfterEachCallback and get custom annotation value like that:
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestWatcher;
public class MyExtention implements TestWatcher, AfterEachCallback {
#Override public void testSuccessful(ExtensionContext context) {
if (context.getElement().isPresent() && context.getElement().get().isAnnotationPresent(MyCustomAnnotation.class)) {
int val = context.getElement().get().getAnnotation(MyCustomAnnotation.class).value();
// Report on success
}
}
#Override public void afterEach(ExtensionContext context) throws Exception {
if (context.getElement().isPresent() && context.getElement().get().isAnnotationPresent(MyCustomAnnotation.class)) {
int val = context.getElement().get().getAnnotation(MyCustomAnnotation.class).value();
// Report each
}
}
}

How to get hold of AutomatedInstallData within IzPack 5 InstallerListener methods?

I've tried to find any info on that but failed, maybe someone here can help.
I'm using IzPack 5 since couple of weeks and that's what I started with, so I have no prior IzPack 4 experience.
What I want to do is the following:
Give the user an opportunity to select data directory via
UserInputPanel (works fine)
Validate the entry by checking if the
database already resides there (works fine)
Depending on whether
the DB already exists and if "force" flag specified on the
UserInputPanel create the database after the packs have been
installed
This last step, that's what I can't see how to do.
I hava a java class that implements InstallerListener interface:
public class IzPackInstaller implements com.izforge.izpack.api.data.DynamicInstallerRequirementValidator,
com.izforge.izpack.api.event.InstallerListener {
It's the same class I use for both data validation / db existance check on step 2 and creation on step 3, just for convinience reasons, but it shouldn't matter
I override
#Override
public void afterInstallerInitialization(AutomatedInstallData data)
throws Exception {
System.out.println("Called afterInstallerInitialization");
System.out.println("db.location=" + data.getVariable("db.location"));
System.out.println("db.force.creation=" + data.getVariable("db.force.creation"));
}
but it seems to be deprecated alltogether and is never called in runtime - checked with System.out's.
The same is valid for:
#Override
public void afterPacks(AutomatedInstallData data,
AbstractUIProgressHandler handler) throws Exception {
System.out.println("Never called!");
}
I also override
#Override
public void afterPacks(List<Pack> packs, ProgressListener listener) { }
which is called allright, but how to get hold of AutomatedInstallData within this method? Or how else can I read installer variables at this stage?
I thought of creating a singleton, which I would initialize with the variables during DynamicInstallerRequirementValidator.validateData() call and get the variables at a later point in time, but it's ugly and sounds like a nasty workaround - there should be a way to implement InstallerListener interface and be able to use the variables, shouldn't it?
I'd be really grateful for any hints...
Anton
This is not a very clean solution but there is a way to get a hold of AutomatedInstallData really anywhere in running izpack java without actually overriding some method etc. I would just not suggest it in the first place because it is a little tricky :)
public class Test {
InstallerContainer container = new ConsoleInstallerContainer();
AutomatedInstaller automatedInstaller = container.getComponent(AutomatedInstaller.class);
AutomatedInstallData installData;
public Test() throws IllegalAccessException, NoSuchFieldException {
Field f = AutomatedInstaller.class.getDeclaredField("installData");
f.setAccessible(true);
installData = (AutomatedInstallData)f.get(automatedInstaller);
}
etc...
Now you will have access to the object AutomatedInstallData and its methods.

Which eclipse plugin implements Ctrl+PageDown or M1+PageDown

I am learning eclipse plugin development and a great deal of learning can be done by looking at the implementation of an existing builtin plugin itself.
While I was looking for a shortcut to switch between tabs I found this --> Eclipse HotKey: how to switch between tabs?
However I am not able to search the command /key binding/ Handler class that actually implements the Ctrl+PageDown key binding.
Similarly, I was able to find the key binding and the command of of M3+PAGE_DOWN (ALT+PAGE_DOWN) in plugins/org.eclipse.ui_some_version.jar (org.eclipse.ui_3.103.0.v20120705-114351.jar in my case) but not the Handler.
How can I find these out? Which plugin should I refer to?
Those commands get handled programatically inside
org.eclipse.ui.part.MultiPageEditorPart.
Good tools for analysing the origin of elements are the "Plug-In Registry" View, the "Plug-In Spy" and Google.
You can find the handler in org.eclipse.ui.workbench (see class org.eclipse.ui.part.MultiPageEditorPart)
The handler is defined programmatically and not declaratively:
public abstract class MultiPageEditorPart extends EditorPart implements IPageChangeProvider {
private static final String COMMAND_NEXT_SUB_TAB = "org.eclipse.ui.navigate.nextSubTab"; //$NON-NLS-1$
private void initializeSubTabSwitching() {
IHandlerService service = (IHandlerService) getSite().getService(IHandlerService.class);
service.activateHandler(COMMAND_NEXT_SUB_TAB, new AbstractHandler() {
// ...
}
});
}

Can you apply aspects in PostSharp without using attributes?

I know with Castle Windsor, you can register aspects (when using method interception in Windsor as AOP) using code instead of applying attributes to classes. Is the same possible in Postsharp? It's a preference things, but prefer to have aspects matched to interfaces/objects in one place, as opposed to attributes all over.
Update:
Curious if I can assign aspects to interfaces/objects similiar to this:
container.Register(
Component
.For<IService>()
.ImplementedBy<Service>()
.Interceptors(InterceptorReference.ForType<LoggingAspect>()).Anywhere
);
If you could do this, you would have the option of NOT having to place attributes on assemblies/class/methods to apply aspects. I can then have one code file/class that contains which aspects are applied to which class/methods/etc.
Yes. You can either use multicasting (http://www.sharpcrafters.com/blog/post/Day-2-Applying-Aspects-with-Multicasting-Part-1.aspx , http://www.sharpcrafters.com/blog/post/Day-3-Applying-Aspects-with-Multicasting-Part-2.aspx) or you can use aspect providers (http://www.sharpcrafters.com/blog/post/PostSharp-Principals-Day-12-e28093-Aspect-Providers-e28093-Part-1.aspx , http://www.sharpcrafters.com/blog/post/PostSharp-Principals-Day-13-e28093-Aspect-Providers-e28093-Part-2.aspx).
Example:
using System;
using PostSharp.Aspects;
using PostSharp.Extensibility;
[assembly: PostSharpInterfaceTest.MyAspect(AttributeTargetTypes = "PostSharpInterfaceTest.Interface1", AttributeInheritance = MulticastInheritance.Multicast)]
namespace PostSharpInterfaceTest
{
class Program
{
static void Main(string[] args)
{
Example e = new Example();
Example2 e2 = new Example2();
e.DoSomething();
e2.DoSomething();
Console.ReadKey();
}
}
class Example : Interface1
{
public void DoSomething()
{
Console.WriteLine("Doing something");
}
}
class Example2 : Interface1
{
public void DoSomething()
{
Console.WriteLine("Doing something else");
}
}
interface Interface1
{
void DoSomething();
}
[Serializable]
class MyAspect : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine("Entered " + args.Method.Name);
}
}
}
I recommend that if you have complex requirements for determining which types get certain aspects that you consider creating an aspect provider instead.
Have a look at LOOM.NET, there you have a post compiler and a runtime weaver. With the later one you are able to archive exactly what you want.
It should be possible to use the PostSharp XML configuration. The XML configuration is the unification of the Plug-in and Project models in the project loader.
Description of .psproj could be found at http://www.sharpcrafters.com/blog/post/Configuring-PostSharp-Diagnostics-Toolkits.aspx.
Note, that I've only seen examples how PostSharp Toolkits use this XML configuration.
But it should work for custom aspects the same way.
Warning: I've noticed that installation of a PostSharp Toolkit from Nuget overwrites existing psproj file. So do not forget to back up it.