PsiJavaDirectoryImpl.checkCreateFile() broken?
I have a plugin for a JVM language (Gosu). If the user tries to create a file "Foo.gs" when there is already a file "Foo.java", we throw
IncorrectOperationException
However, if the file "Foo.gs" is created first, and the user tries to create "Foo.java" or our code calls
pkgDir.createFile("Foo.java")
the code ends up in PsiJavaDirectoryImpl#checkCreateFile() which does the following:
final FileType type = FileTypeManager.getInstance().getFileTypeByFileName(name);
if (type == StdFileTypes.CLASS && ProjectRootManager.getInstance(getProject()).getFileIndex().isInSource(getVirtualFile())) {
throw new IncorrectOperationException("Cannot create class-file");
}
In the call, name is "Foo.java" and type is an instance of JavaFileType, but StdFileTypes.CLASS is an instance of JavaClassFileType so the == comparison is always false. In some other places in JetBrains code, the test is done using
type.equals(StdFileTypes.CLASS)
which is also false in this case. It seems like the intent is to look for another CLASS file with the same name but different extension.
1. Is this a bug?
2. Given that we have another file type other than JavaFileType that produces .class files, how can we prevent creation of "Foo.java" when, for example, "Foo.gs" (Gosu) already exists?
Please sign in to leave a comment.
Hi,
1) I don't think that there is a bug as IDEA checks that the file can be created (exact match of the file name) and that compilation would not produce same named file.
2) is it normal to have mixed java/gosu files in one directory together with class files? E.g. when 2 java classes A and B exist in file A, another top level class B can be created but then highlighted duplicated class. I don't hear any complaints about that actually.
1) Ah, I get it. That particular code is just checking that there isn't a .class file that would be duplicated by the output of compiling the new .java file, so the code was not meant to detect the situation we have. What if a project uses several JVM languages, and each language produces class files using the name (without file type) of the file? For example, both Foo.gs and Foo.java result in Foo.class, typically in a different location but the same package. Having both Gosu and Java source files in the same package is allowed, since it allows the developer to choose the most appropriate language.
2) Our IDE plugin tries to prevent a collision between Gosu and Java files in the same package with the same name. If the Foo.java file is created first, we throw IncorrectOperationException if the user tries to create Foo.gs in the same package. But if the Foo.gs file is created first and the user tries to create Foo.java, Idea just lets them do it. Is there a check or inspection anywhere that notices that compiling both files will cause overwriting of the same Foo.class file?
2) yes, the duplicated class check exists. It calls `com.intellij.psi.JavaPsiFacade#findClasses` so it should find JVM classes, not only java ones. The check is here: `com.intellij.codeInsight.daemon.impl.analysis.HighlightClassUtil#checkDuplicateTopLevelClass`
Thank you!