Best way to detect and fix incorrect module type?

This is somewhat of a continuation of a previous question that I posted.  Basically when users of my plugin create a new project or module from existing sources, in particular from VCS, the resulting module is not of the correct type.  This causes other behavioral issues, and the current workaround is to have the user delete the existing module and replace it with a new module of the correct type on the same source root.  This is clunky at best, and it's leading to quite a few questions from users.

In my previous question I asked whether there might be some way to have the new module be created of the correct type initially, but it doesn't sound like that's supported.  I'm now planning to take a different approach where I can detect modules of the incorrect type and migrate them to be of the correct type.  I've looked at a few different EPs including checkoutCompletedListener, projectOpenProcessor, and of course localInspection.  The first two don't seem like good fits because in reality I'd like to detect this quickly in just about any situation, not just when a module in introduced via VCS checkout or when a project is opened (that doesn't detect new modules).  A global inspection with an associated intention seems like the best way I've found so far, but before I go make something harder than it should be, I figured I'd ask for guidance here.

For what it's worth, I already have a framework.detector that can detect and prompt for the module facet type, though even that isn't working as well as I'd prefer since the implementation of FacetBasedFrameworkDetector.getFileType() can only return a single file type, but my plugin supports multiple custom file types that might identify the need for a facet.  I guess that's a second question...can I have more than one file type be used for detection?

Okay, I'll start with that.  Thanks in advance!

UPDATE: Now I'm looking at the editorNotificationProvider EP.  Looks promising.

0
5 comments

I suspect that you'll need to do this at project open, since AFAIK you can't change module types with the project open. I guess you could always delete the module and recreate it with the same name but the new type - I'm not sure what side effects that might have.

If you do want to do it as a migration on project open, there's some infrastructure for doing various sorts of migrations starting at com.intellij.conversion.ConverterProvider. You can migrate different aspects of the project at startup and it'll show the user a dialog with what's going to happen, and backup the affected files etc. The migrations work on the XML defining the project rather than the usual project model, there are some examples in the community source.

0

Thanks, Colin!  The combination of an editorNotificationProvider to detect the situation/prompt the user for conversion (which closes and reopens the current project) and a project.converterProvider to safely perform that conversion has given me what I needed in a very elegant fashion.

0

Nice! How did you close and reopen the project, out of curiosity?


0
ApplicationManager.getApplication().invokeLater(new Runnable()
{
    @Override
    public void
run()
    {
        ProjectManager.getInstance().closeProject(project);
    }
});

ApplicationManager.getApplication().invokeLater(new Runnable()
{
    @Override
    public void
run()
    {
        try
        
{
            ProjectManager.getInstance().loadAndOpenProject(project.getBaseDir().getPath());
        }
        catch (Exception e)
        {
            handleError(e);
        }
    }
});
0

Okay, this is working very well now when I use File>New>Project from Version Control, but it doesn't work properly when I do File>New>Project/Module from Existing Sources (which includes Check out from Version Control from the dialog shown when no projects are open since that checks out the source and then starts the Project from Existing Sources wizard).

When I do the latter, it takes me through a wizard that starts with options to Create project from existing sources or Import project from external model.  I choose Create project from existing sources and click Next.  In the next step, I'm asked for a project name and location, and the defaults are fine.  In the third step, it scans for potential source roots.  I've registered a projectStructureDetector EP in my plugin to find these properly, so that step shows the proper source roots.  The fourth step tries to detect frameworks, but it finds none because my plugin doesn't have any frameworks.  When I then click Finish, the new project is opened with no modules.  Obviously something is keeping it from creating a module with the source root I supplied in the third step.  Any idea what that might be and how I might allow this to complete successfully with a module associated with that source root?

UPDATE: Never mind.  I figured it out,  I was missing a few things in my projectStructureDetector implementation.  I have it working now.

0

Please sign in to leave a comment.