Repository: hannah-sten/texify-idea
Issue: jpeg file not found, but jpg does get found

#### Type of JetBrains IDE (IntelliJ, PyCharm, etc.) and version
PyCharm 2023.1.1 (Professional Edition)
Build #PY-231.8770.66

#### Operating System

Windows

#### TeXiFy IDEA version

0.7.31

#### What I did (steps to reproduce)

I tried using `\\includegraphics` with a `.jpeg` image.
The IDE complained that it could not find the file.

I changed the file extension to `.jpg`, then the IDE did not complain anymore.

#### Minimal example to reproduce the problem

1. Save a JPEG/JPG image under `path/to/image1.jpeg` (extension is important, directory structure is not).
2. Save another JPEG/JPG image under `path/to/image2.jpg` (extension is important, directory structure is not).
3. Try including the images in the document without explicitly stating the file extension like e.g.

```latex
\\documentclass{article}
\\begin{document}
    \\begin{figure}[h]
        \\includegraphics[scale=0.5]{path/to/image1}
    \\end{figure}

    \\begin{figure}[h]
        \\includegraphics[scale=0.5]{path/to/image2}
    \\end{figure}
\\end{document}
```

#### Expected behavior

Both the image with extension `.jpeg` and the image with extension `.jpg` can be found by the IDE.

#### Actual behavior

The image with extension `.jpeg` cannot be found by the IDE, while the image with extension `.jpg` can be found by the IDE.

Changed files:
src/nl/hannahsten/texifyidea/lang/commands/RequiredFileArgument.kt, src/nl/hannahsten/texifyidea/util/files/PsiFile.kt, src/nl/hannahsten/texifyidea/lang/commands/RequiredPicturePathArgument.kt, src/nl/hannahsten/texifyidea/util/parser/LatexCommandsImplMixinUtil.kt, src/nl/hannahsten/texifyidea/run/latex/logtab/LatexOutputListener.kt, src/nl/hannahsten/texifyidea/completion/pathcompletion/LatexPathProviderBase.kt, src/nl/hannahsten/texifyidea/lang/commands/LatexGenericRegularCommand.kt, src/nl/hannahsten/texifyidea/util/magic/FileMagic.kt, src/nl/hannahsten/texifyidea/reference/InputFileReference.kt, src/nl/hannahsten/texifyidea/util/files/VirtualFile.kt

diff --git a/src/nl/hannahsten/texifyidea/completion/pathcompletion/LatexPathProviderBase.kt b/src/nl/hannahsten/texifyidea/completion/pathcompletion/LatexPathProviderBase.kt
index c32497e75..0793f46c4 100644
--- a/src/nl/hannahsten/texifyidea/completion/pathcompletion/LatexPathProviderBase.kt
+++ b/src/nl/hannahsten/texifyidea/completion/pathcompletion/LatexPathProviderBase.kt
@@ -30,7 +30,7 @@ abstract class LatexPathProviderBase : CompletionProvider<CompletionParameters>(
 
     private var parameters: CompletionParameters? = null
     private var resultSet: CompletionResultSet? = null
-    private var validExtensions: Set<String>? = null
+    private var validExtensions: List<String>? = null
     private var absolutePathSupport = true
 
     companion object {
diff --git a/src/nl/hannahsten/texifyidea/lang/commands/LatexGenericRegularCommand.kt b/src/nl/hannahsten/texifyidea/lang/commands/LatexGenericRegularCommand.kt
index ba5ef8c7c..afd4026a3 100644
--- a/src/nl/hannahsten/texifyidea/lang/commands/LatexGenericRegularCommand.kt
+++ b/src/nl/hannahsten/texifyidea/lang/commands/LatexGenericRegularCommand.kt
@@ -15,6 +15,7 @@ import nl.hannahsten.texifyidea.lang.LatexPackage.Companion.TEXTCOMP
 import nl.hannahsten.texifyidea.lang.LatexPackage.Companion.ULEM
 import nl.hannahsten.texifyidea.lang.LatexPackage.Companion.VARIOREF
 import nl.hannahsten.texifyidea.lang.LatexPackage.Companion.XCOLOR
+import nl.hannahsten.texifyidea.util.magic.FileMagic
 
 /**
  * @author Hannah Schellekens
@@ -143,7 +144,7 @@ enum class LatexGenericRegularCommand(
     INCLUDEFROM("includefrom", RequiredFolderArgument("absolute path"), RequiredFileArgument("filename", false, false, "tex"), dependency = LatexPackage.IMPORT),
     INPUT("input", RequiredFileArgument("sourcefile", true, false, "tex")),
     INPUTFROM("inputfrom", RequiredFolderArgument("absolute path"), RequiredFileArgument("filename", false, false, "tex"), dependency = LatexPackage.IMPORT),
-    INCLUDEGRAPHICS("includegraphics", "key-val-list".asOptional(), RequiredPicturePathArgument("imagefile", true, false, "pdf", "png", "jpg", "eps", "tikz"), dependency = GRAPHICX),
+    INCLUDEGRAPHICS("includegraphics", "key-val-list".asOptional(), RequiredPicturePathArgument("imagefile", isAbsolutePathSupported = true, commaSeparatesArguments = false, FileMagic.graphicFileExtensions), dependency = GRAPHICX),
     INCLUDEONLY("includeonly", RequiredFileArgument("sourcefile", false, true, "tex")),
     INDEXNAME("indexname", "name".asRequired()),
     INDEXSPACE("indexspace"),
diff --git a/src/nl/hannahsten/texifyidea/lang/commands/RequiredFileArgument.kt b/src/nl/hannahsten/texifyidea/lang/commands/RequiredFileArgument.kt
index c6025c10c..c5d9deee0 100644
--- a/src/nl/hannahsten/texifyidea/lang/commands/RequiredFileArgument.kt
+++ b/src/nl/hannahsten/texifyidea/lang/commands/RequiredFileArgument.kt
@@ -20,7 +20,7 @@ import java.util.regex.Pattern
  */
 open class RequiredFileArgument(name: String?, open val isAbsolutePathSupported: Boolean = true, open val commaSeparatesArguments: Boolean, vararg extensions: String) : RequiredArgument(name!!, Type.FILE), FileNameMatcher, FileExtensionMatcher {
 
-    lateinit var supportedExtensions: Set<String>
+    lateinit var supportedExtensions: List<String>
     lateinit var defaultExtension: String
         private set
     private var pattern: Pattern? = null
@@ -38,7 +38,7 @@ open class RequiredFileArgument(name: String?, open val isAbsolutePathSupported:
      * extensions, all files will match.
      */
     private fun setExtensions(vararg extensions: String) {
-        val supportedExtensions = mutableSetOf<String>()
+        val supportedExtensions = mutableListOf<String>()
         val regex = StringBuilder(".*")
         if (extensions.isEmpty()) {
             setRegex(regex.toString())
@@ -74,6 +74,6 @@ open class RequiredFileArgument(name: String?, open val isAbsolutePathSupported:
     }
 
     override fun matchesExtension(extension: String): Boolean {
-        return supportedExtensions.contains(extension)
+        return supportedExtensions.contains(extension.lowercase(Locale.getDefault()))
     }
 }
\\ No newline at end of file
diff --git a/src/nl/hannahsten/texifyidea/lang/commands/RequiredPicturePathArgument.kt b/src/nl/hannahsten/texifyidea/lang/commands/RequiredPicturePathArgument.kt
index d349eda8b..1e909afa6 100644
--- a/src/nl/hannahsten/texifyidea/lang/commands/RequiredPicturePathArgument.kt
+++ b/src/nl/hannahsten/texifyidea/lang/commands/RequiredPicturePathArgument.kt
@@ -4,4 +4,4 @@ package nl.hannahsten.texifyidea.lang.commands
  * @author Lukas Heiligenbrunner
  */
 // We have to explicitly override isAbsolutePathSupported to avoid a NoSuchMethodError
-class RequiredPicturePathArgument(name: String, override val isAbsolutePathSupported: Boolean = true, override val commaSeparatesArguments: Boolean = true, vararg extension: String) : RequiredFileArgument(name, isAbsolutePathSupported, commaSeparatesArguments, *extension)
\\ No newline at end of file
+class RequiredPicturePathArgument(name: String, override val isAbsolutePathSupported: Boolean = true, override val commaSeparatesArguments: Boolean = true, extension: List<String>) : RequiredFileArgument(name, isAbsolutePathSupported, commaSeparatesArguments, *extension.toTypedArray())
\\ No newline at end of file
diff --git a/src/nl/hannahsten/texifyidea/reference/InputFileReference.kt b/src/nl/hannahsten/texifyidea/reference/InputFileReference.kt
index 65a6a900e..30482319d 100644
--- a/src/nl/hannahsten/texifyidea/reference/InputFileReference.kt
+++ b/src/nl/hannahsten/texifyidea/reference/InputFileReference.kt
@@ -32,7 +32,7 @@ import nl.hannahsten.texifyidea.util.magic.CommandMagic
 class InputFileReference(
     element: LatexCommands,
     val range: TextRange,
-    val extensions: Set<String>,
+    val extensions: List<String>,
     val defaultExtension: String
 ) : PsiReferenceBase<LatexCommands>(element) {
 
diff --git a/src/nl/hannahsten/texifyidea/run/latex/logtab/LatexOutputListener.kt b/src/nl/hannahsten/texifyidea/run/latex/logtab/LatexOutputListener.kt
index fdf3705d2..e711f670b 100644
--- a/src/nl/hannahsten/texifyidea/run/latex/logtab/LatexOutputListener.kt
+++ b/src/nl/hannahsten/texifyidea/run/latex/logtab/LatexOutputListener.kt
@@ -147,7 +147,7 @@ class LatexOutputListener(
     }
 
     private fun findProjectFileRelativeToMain(fileName: String?): VirtualFile? =
-        mainFile?.parent?.findFile(fileName ?: mainFile.name, setOf("tex"))
+        mainFile?.parent?.findFile(fileName ?: mainFile.name, listOf("tex"))
 
     /**
      * Reset the tree view and the message list when starting a new run. (latexmk)
diff --git a/src/nl/hannahsten/texifyidea/util/files/PsiFile.kt b/src/nl/hannahsten/texifyidea/util/files/PsiFile.kt
index ccc0a988d..f55a54e00 100644
--- a/src/nl/hannahsten/texifyidea/util/files/PsiFile.kt
+++ b/src/nl/hannahsten/texifyidea/util/files/PsiFile.kt
@@ -134,7 +134,7 @@ private fun PsiFile.referencedFiles(files: MutableCollection<PsiFile>, rootFile:
  *         The path relative to this file.
  * @return The found file, or `null` when the file could not be found.
  */
-fun PsiFile.findFile(path: String, extensions: Set<String>? = null): PsiFile? {
+fun PsiFile.findFile(path: String, extensions: List<String>? = null): PsiFile? {
     if (project.isDisposed) return null
     val directory = containingDirectory?.virtualFile
 
@@ -168,7 +168,7 @@ fun PsiFile.findIncludedFile(command: LatexCommands): Set<PsiFile> {
     return arguments.filter { it.isNotEmpty() }.mapNotNull {
         val extension = FileMagic.automaticExtensions[command.name]
         if (extension != null) {
-            findFile(it, setOf(extension))
+            findFile(it, listOf(extension))
         }
         else {
             findFile(it)
@@ -183,7 +183,7 @@ fun PsiFile.findIncludedFile(command: LatexCommands): Set<PsiFile> {
  *         The path relative to {@code original}.
  * @return The found file, or `null` when the file could not be found.
  */
-fun PsiFile.scanRoots(path: String, extensions: Set<String>? = null): PsiFile? {
+fun PsiFile.scanRoots(path: String, extensions: List<String>? = null): PsiFile? {
     val rootManager = ProjectRootManager.getInstance(project)
     rootManager.contentSourceRoots.forEach { root ->
         val file = root.findFile(
diff --git a/src/nl/hannahsten/texifyidea/util/files/VirtualFile.kt b/src/nl/hannahsten/texifyidea/util/files/VirtualFile.kt
index 3559b7501..964628eee 100644
--- a/src/nl/hannahsten/texifyidea/util/files/VirtualFile.kt
+++ b/src/nl/hannahsten/texifyidea/util/files/VirtualFile.kt
@@ -65,7 +65,7 @@ fun findVirtualFileByAbsoluteOrRelativePath(path: String, project: Project): Vir
  *         Set of all supported extensions to look for.
  * @return The matching file, or `null` when the file couldn't be found.
  */
-fun VirtualFile.findFile(filePath: String, extensions: Set<String> = emptySet()): VirtualFile? {
+fun VirtualFile.findFile(filePath: String, extensions: List<String> = emptyList()): VirtualFile? {
     try {
         val isAbsolute = File(filePath).isAbsolute
         var file = if (!isAbsolute) {
diff --git a/src/nl/hannahsten/texifyidea/util/magic/FileMagic.kt b/src/nl/hannahsten/texifyidea/util/magic/FileMagic.kt
index 904198281..cb0ace8b1 100644
--- a/src/nl/hannahsten/texifyidea/util/magic/FileMagic.kt
+++ b/src/nl/hannahsten/texifyidea/util/magic/FileMagic.kt
@@ -8,8 +8,9 @@ object FileMagic {
 
     /**
      * All file extensions of files that can be included (and where the included files contain language that needs to be considered).
+     * sty extensions are preferred over tex extensions for the case when e.g. a main.tex file includes a main.sty file (generally it will not be the other way around).
      */
-    val includeExtensions = hashSetOf("tex", "sty", "cls", "bib")
+    val includeExtensions = listOf("sty", "tex", "cls", "bib")
 
     val automaticExtensions = mapOf(
         INCLUDE.cmd to LatexFileType.defaultExtension,
@@ -59,6 +60,8 @@ object FileMagic {
 
     /**
      * All extensions for graphic files.
+     * This order is determined by the order in which \\includegraphics tries the extensions to find files, as can be seen with
+     * texdef -t pdflatex -p graphicx Gin@extensions
      */
-    val graphicFileExtensions = setOf("eps", "pdf", "png", "jpeg", "jpg", "jbig2", "jp2")
+    val graphicFileExtensions = listOf("pdf", "png", "jpg", "mps", "jpeg", "jbig2", "jb2", "PDF", "PNG", "JPG", "JPEG", "JBIG2", "JB2", "eps")
 }
\\ No newline at end of file
diff --git a/src/nl/hannahsten/texifyidea/util/parser/LatexCommandsImplMixinUtil.kt b/src/nl/hannahsten/texifyidea/util/parser/LatexCommandsImplMixinUtil.kt
index 366022afa..1e2905c36 100644
--- a/src/nl/hannahsten/texifyidea/util/parser/LatexCommandsImplMixinUtil.kt
+++ b/src/nl/hannahsten/texifyidea/util/parser/LatexCommandsImplMixinUtil.kt
@@ -64,7 +64,7 @@ fun LatexCommands.getFileArgumentsReferences(): List<InputFileReference> {
     if (name == LatexGenericRegularCommand.DOCUMENTCLASS.cmd && SUBFILES.name in getRequiredParameters() && getOptionalParameterMap().isNotEmpty()) {
         val range = this.firstChildOfType(LatexParameter::class)?.textRangeInParent
         if (range != null) {
-            inputFileReferences.add(InputFileReference(this, range.shrink(1), setOf("tex"), "tex"))
+            inputFileReferences.add(InputFileReference(this, range.shrink(1), listOf("tex"), "tex"))
         }
     }