Is the change to scratch files to FileType in the latest releases intentional?

What I am refering to is in the latest releases creating a scratch file and selecting the file type for a plugin results in the accept() call in the editor provider with a FileType set to plain text. In older releases the right file type was given.

This means that the scratch file will not be accepted by the plugin because getFileType() does not return an instance that the plugin expects.

To make it work in the new release you need to go a step further to recognize Scratch files of plugin's type:

 
public static boolean accept(@NotNull VirtualFile file) {
    String name = file.getName();
    String fileExt = file.getExtension();
 
 
public static boolean accept(@NotNull VirtualFile file) {
    String name = file.getName();
    String fileExt = file.getExtension();
    FileType fileType = file.getFileType();
    boolean doAccept = fileType instanceof MultiMarkdownFileType;

    if (!doAccept) {
        try {
            // Issue: #14 scratch files have to be matched differently
            //ScratchFileService fileService = ScratchFileService.getInstance();
            //PerFileMappings<Language> scratchesMapping = fileService.getScratchesMapping();
            //Language language = scratchesMapping.getMapping(file);
            //doAccept = language instanceof MultiMarkdownLanguage;

            // Issue: #15 class not found ScratchFileService, so we take care of it through reflection
            
Class<?> ScratchFileService = Class.forName("com.intellij.ide.scratch.ScratchFileService");
            Method getInstance = ScratchFileService.getMethod("getInstance");
            Method getScratchesMapping = ScratchFileService.getMethod("getScratchesMapping");
            Object fileService = getInstance.invoke(ScratchFileService);
            PerFileMappings<Language> mappings = (PerFileMappings<Language>) getScratchesMapping.invoke(fileService);
            Language language = mappings.getMapping(file);
            doAccept = language instanceof MultiMarkdownLanguage;
        } catch (Exception ex) {
            // no such beast
        
}
    }


Now it works on old and new releases. I got to use reflection API. But....

Am I missing something because it seems like a hell of a lot of work to accept scratch files for the plugin.

3 comments
Comment actions Permalink

Hi Vladimir,

See also my related YouTrack issue: https://youtrack.jetbrains.com/issue/IDEA-136560. I must admit I still don't understand all the intricacies of this, and my plugin still doesn't support scratch files correctly.

Cheers,
Colin

0
Comment actions Permalink

I don't know the intricacies of what is intended but it used to be that if the user selected your plugin's language for the scratch file by the time the virtual file came down to the plugin it was already associated with the right file type. Now it is just plain-text and you have to go through the ScratchFileService to get the mapping for the file to the language and check the language.

Not a big deal but if you use the direct approach then your plugin will not work with earlier releases because the ScratchFileService class does not exist. I found a solution by using the reflection API so that I can get the serivice on later releases and not to load on earlier ones, but it seemed a bit too ugly to be the intended result so I posted this quesion. I also added my two cents' worth to the discussion on youtrack that you referered to.

Here is what I use in my EditorProvider accept() function to figure out if the file or scratch file should be accepted:

 
public boolean accept(@NotNull VirtualFile file) {
    String fileExt = file.getExtension();
    FileType fileType = file.getFileType();
    boolean doAccept = fileType instanceof MultiMarkdownFileType;

    if (!doAccept) {
        try {
            // Issue: #14 scratch files have to be matched differently
            //ScratchFileService fileService = ScratchFileService.getInstance();
            //PerFileMappings<Language> scratchesMapping = fileService.getScratchesMapping();
            //Language language = scratchesMapping.getMapping(file);
            //doAccept = language instanceof MultiMarkdownLanguage;

            // Issue: #15 class not found ScratchFileService, so we take care of it through reflection
            
Class<?> ScratchFileService = Class.forName("com.intellij.ide.scratch.ScratchFileService");
            Method getInstance = ScratchFileService.getMethod("getInstance");
            Method getScratchesMapping = ScratchFileService.getMethod("getScratchesMapping");
            Object fileService = getInstance.invoke(ScratchFileService);
            PerFileMappings<Language> mappings = (PerFileMappings<Language>) getScratchesMapping.invoke(fileService);
            Language language = mappings.getMapping(file);
            doAccept = language instanceof MultiMarkdownLanguage;
        } catch (Exception ex) {
            // no such beast
        
}
    }

    if (!doAccept && fileExt != null) {
        for (String ext : MultiMarkdownFileTypeFactory.getExtensions()) {
            if (ext.equals(fileExt)) {
                doAccept = true;
                break;
            }
        }
    }
    return doAccept;
}


I left the code to call the service without reflection API commented out for reference. The reflection API is hard to follow without having original code as reference. Feel free to use it, if it solves your problem.

0
Comment actions Permalink

It seems that the break with the past is sort of by design but the final solution is still being debated.

i did post a work around that I found, but think it is on the ugly side.

0

Please sign in to leave a comment.