Skip to content

Commit

Permalink
Merge pull request #3855 from Hannah-Sten/unresolved-reference
Browse files Browse the repository at this point in the history
  • Loading branch information
PHPirates authored Jan 27, 2025
2 parents 937cd70 + 5015eee commit cc2b613
Show file tree
Hide file tree
Showing 27 changed files with 477 additions and 245 deletions.
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ jobs:
test:
runs-on: ${{ matrix.os }}
if: github.event.pull_request.draft == false
timeout-minutes: 50
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
Expand Down
46 changes: 45 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,49 @@

### Fixed

## [0.9.10-alpha.6] - 2025-01-21

### Added

* Refresh file set cache in background
* Support Tectonic V2 CLI in run configuration
* Add basic support for multiple inputs in Tectonic.toml
* Improve performance of file set cache used by inspections
* Support label references to user defined listings environment
* Add option to disable automatic compilation in power save mode
* Convert automatic compilation settings to a combobox
* Add experimental support for the addtoluatexpath package
* Add inspection to check for LaTeX package updates
* Add checkboxes to graphic insertion wizard for relative width or height
* Add sections to breadcrumbs
* Improve performance when starting a run configuration and when using autocompletion directly after starting the IDE
* Change order in structure view to match source file and sectioning level
* Add command redefinitions to command definition filter in structure view
* Add support for automatic language injection on the minted environment
* Add support for automatic detection of custom command aliases for include commands
* Add support for DeclareGraphicsExtensions
* Add inspection to warn about a missing reference for a glossary occurrence
* Do not fold sections in a command definition
* Include optional parameters in spellcheck, if it contains text
* Improve performance of finding files to be indexed
* Show formatted file path in file not found inspection quickfix name
* Automatically index bibliography files outside the project that are included by an absolute path
* Disable quotes inspection when TeX ligatures are disabled by fontspec
* Inspections can now be suppressed for any single line, or block of text

### Fixed

* Fix parse error when using commands with arguments in parameter of \href or \url
* Fix parse error when using parentheses in a group in a key value command argument
* Fix parse erron when using inline math in cases* environment in inline math
* Fix exceptions #3813, #3818
* Fix false positive non-breaking space warning for \nameref
* Fix confusion with \micro and \mu unicode characters
* Fix auto import from local bibtex file on Windows
* Fix false positive for duplicate command definition inspection in if/else
* Fix LaTeX files not showing up when choosing main file in run configuration
* Fix various issues with the Grazie implementation, in particular default rules for Grazie Pro

## [0.9.10-alpha.5] - 2024-12-30

### Added
Expand Down Expand Up @@ -542,7 +585,8 @@ Thanks to @jojo2357 and @MisterDeenis for contributing to this release!
* Fix some intention previews. ([#2796](https://github.com/Hannah-Sten/TeXiFy-IDEA/issues/2796))
* Other small bug fixes and improvements. ([#2776](https://github.com/Hannah-Sten/TeXiFy-IDEA/issues/2776), [#2774](https://github.com/Hannah-Sten/TeXiFy-IDEA/issues/2774), [#2765](https://github.com/Hannah-Sten/TeXiFy-IDEA/issues/2765)-[#2773](https://github.com/Hannah-Sten/TeXiFy-IDEA/issues/2773))

[Unreleased]: https://github.com/Hannah-Sten/TeXiFy-IDEA/compare/v0.9.10-alpha.5...HEAD
[Unreleased]: https://github.com/Hannah-Sten/TeXiFy-IDEA/compare/v0.9.10-alpha.6...HEAD
[0.9.10-alpha.6]: https://github.com/Hannah-Sten/TeXiFy-IDEA/compare/v0.9.10-alpha.5...v0.9.10-alpha.6
[0.9.10-alpha.5]: https://github.com/Hannah-Sten/TeXiFy-IDEA/compare/v0.9.10-alpha.4...v0.9.10-alpha.5
[0.9.10-alpha.4]: https://github.com/Hannah-Sten/TeXiFy-IDEA/compare/v0.9.10-alpha.3...v0.9.10-alpha.4
[0.9.10-alpha.3]: https://github.com/Hannah-Sten/TeXiFy-IDEA/compare/v0.9.10-alpha.2...v0.9.10-alpha.3
Expand Down
5 changes: 5 additions & 0 deletions Writerside/topics/Contributing-to-the-source-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ But there is an important difference! The `name` is _indexed_ (see `LatexCommand
This means that probably using `name` is recommended, as it would use the index, but it may be completely wrong if the index is not updated correctly.
This can lead to strange behaviour (see e.g. [#1097](https://github.com/Hannah-Sten/TeXiFy-IDEA/issues/1097)), which can be fixed by updating the index correctly.

## Concurrency

Never use the regular `runReadAction` from a coroutine! This read action will block write actions, but in a coroutine the regular cancellation check/exception does not work, which may lead to a deadlock.
See https://plugins.jetbrains.com/docs/intellij/coroutine-read-actions.html#write-allowing-read-action-vs-nonblockingreadaction

## Helpful tools

* <ui-path>Tools | View PSI Structure</ui-path>
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pluginVersion = 0.9.10-alpha.5
pluginVersion = 0.9.10-alpha.7

# Info about build ranges: https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html
# Note that an xyz branch corresponds to version 20xy.z and a since build of xyz.*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ class VfsChangeListener : BulkFileListener {
.forEach {
if (it.file != null) {
// We drop all caches because that is faster than figuring out which cached values need to be updated
ReferencedFileSetService.getInstance().dropAllCaches()
// Mark caches to be deleted, so they will be filled the next time they are requested
ReferencedFileSetService.getInstance().markCacheOutOfDate()
}
}
super.after(events)
Expand Down
23 changes: 20 additions & 3 deletions src/nl/hannahsten/texifyidea/index/IndexUtilBase.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package nl.hannahsten.texifyidea.index

import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.application.smartReadAction
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.SmartPsiElementPointer
import com.intellij.psi.createSmartPointer
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubIndex
import com.intellij.psi.stubs.StubIndexKey
import com.intellij.psi.createSmartPointer
import nl.hannahsten.texifyidea.util.Log
import nl.hannahsten.texifyidea.util.files.documentClassFileInProject
import nl.hannahsten.texifyidea.util.files.findRootFile
Expand Down Expand Up @@ -117,6 +118,7 @@ abstract class IndexUtilBase<T : PsiElement>(
* @param scope
* The scope in which to search for the items.
*/
@Deprecated("Use getItemsNonBlocking")
fun getItems(project: Project, scope: GlobalSearchScope, useCache: Boolean = true): Collection<T> {
if (useCache) {
// Cached values may have become invalid over time, so do a double check to be sure (#2976)
Expand All @@ -127,6 +129,21 @@ abstract class IndexUtilBase<T : PsiElement>(
return result
}

suspend fun getItemsNonBlocking(project: Project, scope: GlobalSearchScope, useCache: Boolean = true): Collection<T> {
if (useCache) {
// Cached values may have become invalid over time, so do a double check to be sure (#2976)
cache[project]?.get(scope)?.let {
return smartReadAction(project) {
it.mapNotNull { pointer -> pointer.element }
.filter { it.isValid }
}
}
}
val result = smartReadAction(project) { getKeys(project) }.flatMap { smartReadAction(project) { getItemsByName(it, project, scope) } }
cache.getOrPut(project) { mutableMapOf() }[scope] = result.map { smartReadAction(project) { it.createSmartPointer() } }
return result
}

/**
* Get all the items in the index that have the given name.
* WARNING This takes significant time because of index access. Be very careful about performance when calling it many times.
Expand All @@ -140,7 +157,7 @@ abstract class IndexUtilBase<T : PsiElement>(
*/
private fun getItemsByName(name: String, project: Project, scope: GlobalSearchScope): Collection<T> {
try {
return runReadAction { StubIndex.getElements(indexKey, name, project, scope, elementClass) }
return StubIndex.getElements(indexKey, name, project, scope, elementClass)
}
catch (e: Exception) {
// For some reason, any issue from any plugin that causes an exception will be raised here and will be attributed to TeXiFy, flooding the backlog
Expand All @@ -162,7 +179,7 @@ abstract class IndexUtilBase<T : PsiElement>(
private fun getKeys(project: Project): Array<String> {
if (!DumbService.isDumb(project) && !project.isDefault) {
try {
return runReadAction { StubIndex.getInstance().getAllKeys(indexKey, project).toTypedArray() }
return StubIndex.getInstance().getAllKeys(indexKey, project).toTypedArray()
}
catch (e: Exception) {
// See above
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import com.jetbrains.rd.util.concurrentMapOf
import nl.hannahsten.texifyidea.algorithm.DFS
import nl.hannahsten.texifyidea.lang.LatexPackage
import nl.hannahsten.texifyidea.util.files.removeFileExtension
import nl.hannahsten.texifyidea.util.runInBackground
import nl.hannahsten.texifyidea.util.runInBackgroundBlocking
import java.util.concurrent.atomic.AtomicBoolean

/**
Expand Down Expand Up @@ -40,7 +40,7 @@ object LatexExternalPackageInclusionCache {
if (isFillingCache.getAndSet(true)) return cache
// ???
runInEdt {
runInBackground(project, "Retrieving LaTeX package inclusions...") { indicator ->
runInBackgroundBlocking(project, "Retrieving LaTeX package inclusions...") { indicator ->
try {
runReadAction { FileBasedIndex.getInstance().getAllKeys(LatexExternalPackageInclusionIndex.Cache.id, project) }.forEach { indexKey ->
runReadAction {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import nl.hannahsten.texifyidea.util.getTexinputsPaths
import nl.hannahsten.texifyidea.util.isTestProject
import nl.hannahsten.texifyidea.util.magic.CommandMagic
import nl.hannahsten.texifyidea.util.parser.requiredParameter
import nl.hannahsten.texifyidea.util.runInBackground
import nl.hannahsten.texifyidea.util.runInBackgroundBlocking
import org.codehaus.plexus.archiver.ArchiverException
import org.codehaus.plexus.archiver.tar.TarBZip2UnArchiver
import org.codehaus.plexus.archiver.tar.TarXZUnArchiver
Expand Down Expand Up @@ -77,7 +77,7 @@ class LatexIndexableSetContributor : IndexableSetContributor() {

// Using the index while building it may be problematic, cache the result and hope it doesn't create too much trouble
if (Cache.externalDirectFileInclusions == null && !DumbService.isDumb(project)) {
runInBackground(project, "Searching for inclusions by absolute path...") {
runInBackgroundBlocking(project, "Searching for inclusions by absolute path...") {
// Bibliography and direct input commands
val commandNames = CommandMagic.includeOnlyExtensions.entries.filter { it.value.contains("bib") || it.value.contains("tex") }.map { it.key }.toSet()
val externalFiles = runReadAction {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package nl.hannahsten.texifyidea.inspections.latex.probablebugs.packages

import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo
import com.intellij.codeInspection.InspectionManager
import com.intellij.codeInspection.LocalQuickFix
Expand All @@ -24,6 +23,7 @@ import nl.hannahsten.texifyidea.reference.InputFileReference
import nl.hannahsten.texifyidea.settings.sdk.LatexSdkUtil
import nl.hannahsten.texifyidea.settings.sdk.TexliveSdk
import nl.hannahsten.texifyidea.util.TexLivePackages
import nl.hannahsten.texifyidea.util.files.rerunInspections
import nl.hannahsten.texifyidea.util.magic.cmd
import nl.hannahsten.texifyidea.util.parser.childrenOfType
import nl.hannahsten.texifyidea.util.parser.requiredParameter
Expand Down Expand Up @@ -155,11 +155,7 @@ class LatexPackageNotInstalledInspection : TexifyInspectionBase() {
override fun onSuccess() {
TexLivePackages.packageList.add(packageName)
// Rerun inspections
DaemonCodeAnalyzer.getInstance(project)
.restart(
filePointer.containingFile
?: return
)
filePointer.containingFile?.rerunInspections()
}
})
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package nl.hannahsten.texifyidea.inspections.latex.probablebugs.packages

import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo
import com.intellij.codeInspection.InspectionManager
import com.intellij.codeInspection.LocalQuickFix
Expand All @@ -20,6 +19,7 @@ import nl.hannahsten.texifyidea.inspections.TexifyInspectionBase
import nl.hannahsten.texifyidea.psi.LatexCommands
import nl.hannahsten.texifyidea.settings.sdk.LatexSdkUtil
import nl.hannahsten.texifyidea.settings.sdk.TexliveSdk
import nl.hannahsten.texifyidea.util.files.rerunInspections
import nl.hannahsten.texifyidea.util.magic.CommandMagic
import nl.hannahsten.texifyidea.util.parser.childrenOfType
import nl.hannahsten.texifyidea.util.parser.requiredParameter
Expand Down Expand Up @@ -129,11 +129,7 @@ class LatexPackageUpdateInspection : TexifyInspectionBase() {
// Clear cache, since we changed something
Cache.availablePackageUpdates = mapOf()
// Rerun inspections
DaemonCodeAnalyzer.getInstance(project)
.restart(
filePointer.containingFile
?: return
)
filePointer.containingFile?.rerunInspections()
}
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import nl.hannahsten.texifyidea.run.pdfviewer.ExternalPdfViewers
import nl.hannahsten.texifyidea.run.pdfviewer.PdfViewer
import nl.hannahsten.texifyidea.run.sumatra.SumatraAvailabilityChecker
import nl.hannahsten.texifyidea.settings.sdk.LatexSdkUtil
import nl.hannahsten.texifyidea.util.runInBackground
import nl.hannahsten.texifyidea.util.runInBackgroundBlocking
import java.awt.event.ItemEvent
import javax.swing.InputVerifier
import javax.swing.JComponent
Expand Down Expand Up @@ -215,7 +215,7 @@ class LatexSettingsEditor(private var project: Project?) : SettingsEditor<LatexR
val txtFile = mainFile.component as TextFieldWithBrowseButton
val filePath = txtFile.text
// Might result in requiring a content root (for relative paths), so we have to run in the background
runInBackground(project, "Resolving main file...") {
runInBackgroundBlocking(project, "Resolving main file...") {
runConfiguration.setMainFile(filePath)
}

Expand Down
33 changes: 32 additions & 1 deletion src/nl/hannahsten/texifyidea/util/General.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.Task.Backgroundable
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange
import com.intellij.platform.ide.progress.withBackgroundProgress
import com.intellij.platform.util.progress.ProgressReporter
import com.intellij.platform.util.progress.reportProgress
import com.intellij.psi.PsiFile
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.regex.Pattern

/**
Expand Down Expand Up @@ -81,14 +88,38 @@ fun TextRange.toIntRange() = startOffset until endOffset
*/
fun Pattern.matches(sequence: CharSequence?) = if (sequence != null) matcher(sequence).matches() else false

fun runInBackground(project: Project?, description: String, function: (indicator: ProgressIndicator) -> Unit) {
/**
* Use [runInBackground] instead
*/
@Deprecated("Use runInBackground, and convert all runReadAction to smartReadAction")
fun runInBackgroundBlocking(project: Project?, description: String, function: (indicator: ProgressIndicator) -> Unit) {
ProgressManager.getInstance().run(object : Backgroundable(project, description) {
override fun run(indicator: ProgressIndicator) {
function(indicator)
}
})
}

/**
* Use [runInBackground] if you have a meaningful coroutine scope.
*/
fun runInBackgroundNonBlocking(project: Project, description: String, function: suspend (ProgressReporter) -> Unit) {
// We don't need to block until it finished
CoroutineScope(Dispatchers.IO).launch {
runInBackground(project, description, function)
}
}

suspend fun runInBackground(project: Project, description: String, function: suspend (ProgressReporter) -> Unit) = withContext(Dispatchers.IO) {
// We don't need to suspend and wait for the result
launch {
withBackgroundProgress(project, description) {
// Work size only allows integers, but we don't know the size here yet, so we start at 100.0%
reportProgress(size = 1000) { function(it) }
}
}
}

fun runInBackgroundWithoutProgress(function: () -> Unit) {
ApplicationManager.getApplication().invokeLater {
function()
Expand Down
Loading

0 comments on commit cc2b613

Please sign in to comment.