mirror of
https://github.com/chylex/IntelliJ-Inspection-Lens.git
synced 2024-11-24 22:42:52 +01:00
Compare commits
2 Commits
223fceb6b9
...
e28804ad5d
Author | SHA1 | Date | |
---|---|---|---|
e28804ad5d | |||
043c02e432 |
@ -1,10 +1,8 @@
|
||||
# Inspection Lens <img align="right" src="logo.png" alt="Plugin Logo">
|
||||
|
||||
IntelliJ plugin that shows errors, warnings, and other inspection highlights inline.
|
||||
Displays errors, warnings, and other inspections inline. Highlights the background of lines with inspections. Supports light and dark themes out of the box.
|
||||
|
||||
After installing the plugin, inspection descriptions will appear after the ends of lines, and the lines will be highlighted with a background color. Shown inspection severities are **Errors**, **Warnings**, **Weak Warnings**, **Server Problems**, **Grammar Errors**, **Typos**, and other inspections from plugins or future IntelliJ versions that have a high enough severity level. Each severity has a different color, with support for both light and dark themes.
|
||||
|
||||
Note: The plugin is not customizable outside the ability to disable/enable the plugin without restarting the IDE. If the defaults don't work for you, I recommend trying the [Inline Error](https://plugins.jetbrains.com/plugin/17302-inlineerror) plugin which can be customized, building your own version of Inspection Lens, or proposing your change in the [issue tracker](https://github.com/chylex/IntelliJ-Inspection-Lens/issues).
|
||||
By default, the plugin shows **Errors**, **Warnings**, **Weak Warnings**, **Server Problems**, **Grammar Errors**, **Typos**, and other inspections with a high enough severity level. Configure visible severities in **Settings | Tools | Inspection Lens**.
|
||||
|
||||
Inspired by [Error Lens](https://marketplace.visualstudio.com/items?itemName=usernamehw.errorlens) for Visual Studio Code, and [Inline Error](https://plugins.jetbrains.com/plugin/17302-inlineerror) for IntelliJ Platform.
|
||||
|
||||
|
@ -8,7 +8,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "com.chylex.intellij.inspectionlens"
|
||||
version = "1.3.3"
|
||||
version = "1.4"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
@ -83,6 +83,12 @@ class EditorLensManager private constructor(private val editor: Editor) {
|
||||
lensManager.hide(highlighter)
|
||||
}
|
||||
}
|
||||
|
||||
object HideAll : Command {
|
||||
override fun apply(lensManager: EditorLensManager) {
|
||||
lensManager.hideAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,6 +15,10 @@ class EditorLensManagerDispatcher(private val lensManager: EditorLensManager) {
|
||||
enqueue(EditorLensManager.Command.Hide(highlighter))
|
||||
}
|
||||
|
||||
fun hideAll() {
|
||||
enqueue(EditorLensManager.Command.HideAll)
|
||||
}
|
||||
|
||||
private fun enqueue(item: EditorLensManager.Command) {
|
||||
synchronized(this) {
|
||||
queuedItems.add(item)
|
||||
|
@ -1,8 +1,9 @@
|
||||
package com.chylex.intellij.inspectionlens.editor
|
||||
|
||||
import com.chylex.intellij.inspectionlens.settings.LensSettingsState
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
||||
import com.intellij.lang.annotation.HighlightSeverity
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.ex.MarkupModelEx
|
||||
import com.intellij.openapi.editor.ex.RangeHighlighterEx
|
||||
@ -48,12 +49,16 @@ internal class LensMarkupModelListener private constructor(editor: Editor) : Mar
|
||||
highlighters.forEach(::showIfValid)
|
||||
}
|
||||
|
||||
private fun hideAll() {
|
||||
lensManagerDispatcher.hideAll()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val EDITOR_KEY = Key<LensMarkupModelListener>(LensMarkupModelListener::class.java.name)
|
||||
private val MINIMUM_SEVERITY = HighlightSeverity.TEXT_ATTRIBUTES.myVal + 1
|
||||
private val SETTINGS_SERVICE = service<LensSettingsState>()
|
||||
|
||||
private fun getFilteredHighlightInfo(highlighter: RangeHighlighter): HighlightInfo? {
|
||||
return HighlightInfo.fromRangeHighlighter(highlighter)?.takeIf { it.severity.myVal >= MINIMUM_SEVERITY }
|
||||
return HighlightInfo.fromRangeHighlighter(highlighter)?.takeIf { SETTINGS_SERVICE.severityFilter.test(it.severity) }
|
||||
}
|
||||
|
||||
private inline fun runWithHighlighterIfValid(highlighter: RangeHighlighter, actionForImmediate: (HighlighterWithInfo) -> Unit, actionForAsync: (HighlighterWithInfo.Async) -> Unit) {
|
||||
@ -101,6 +106,7 @@ internal class LensMarkupModelListener private constructor(editor: Editor) : Mar
|
||||
val listener = editor.getUserData(EDITOR_KEY) ?: return
|
||||
val markupModel = getMarkupModel(editor) ?: return
|
||||
|
||||
listener.hideAll()
|
||||
listener.showAllValid(markupModel.allHighlighters)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
package com.chylex.intellij.inspectionlens.editor
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.SeverityRegistrar
|
||||
import com.intellij.lang.annotation.HighlightSeverity
|
||||
import java.util.function.Predicate
|
||||
|
||||
class LensSeverityFilter(private val hiddenSeverityIds: Set<String>, private val showUnknownSeverities: Boolean) : Predicate<HighlightSeverity> {
|
||||
private val knownSeverityIds = getSupportedSeverities().mapTo(HashSet(), HighlightSeverity::getName)
|
||||
|
||||
override fun test(severity: HighlightSeverity): Boolean {
|
||||
if (!isSupported(severity)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return if (severity.name in knownSeverityIds)
|
||||
severity.name !in hiddenSeverityIds
|
||||
else
|
||||
showUnknownSeverities
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Suppress("DEPRECATION")
|
||||
private fun isSupported(severity: HighlightSeverity): Boolean {
|
||||
return severity > HighlightSeverity.TEXT_ATTRIBUTES && severity !== HighlightSeverity.INFO
|
||||
}
|
||||
|
||||
fun getSupportedSeverities(registrar: SeverityRegistrar = SeverityRegistrar.getSeverityRegistrar(null)): List<HighlightSeverity> {
|
||||
return registrar.allSeverities.filter(::isSupported)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
package com.chylex.intellij.inspectionlens.settings
|
||||
|
||||
import com.chylex.intellij.inspectionlens.editor.LensSeverityFilter
|
||||
import com.intellij.codeInsight.daemon.impl.SeverityRegistrar
|
||||
import com.intellij.lang.annotation.HighlightSeverity
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.editor.event.SelectionEvent
|
||||
import com.intellij.openapi.editor.event.SelectionListener
|
||||
import com.intellij.openapi.editor.markup.TextAttributes
|
||||
import com.intellij.openapi.options.BoundConfigurable
|
||||
import com.intellij.openapi.options.ConfigurableWithId
|
||||
import com.intellij.openapi.ui.DialogPanel
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.ui.DisabledTraversalPolicy
|
||||
import com.intellij.ui.EditorTextFieldCellRenderer.SimpleRendererComponent
|
||||
import com.intellij.ui.components.JBCheckBox
|
||||
import com.intellij.ui.dsl.builder.Cell
|
||||
import com.intellij.ui.dsl.builder.RightGap
|
||||
import com.intellij.ui.dsl.builder.Row
|
||||
import com.intellij.ui.dsl.builder.RowLayout
|
||||
import com.intellij.ui.dsl.builder.bindSelected
|
||||
import com.intellij.ui.dsl.builder.panel
|
||||
import java.awt.Cursor
|
||||
|
||||
class LensApplicationConfigurable : BoundConfigurable("Inspection Lens"), ConfigurableWithId {
|
||||
companion object {
|
||||
const val ID = "InspectionLens"
|
||||
|
||||
private fun getTextAttributes(registrar: SeverityRegistrar, severity: HighlightSeverity): TextAttributes? {
|
||||
return registrar.getHighlightInfoTypeBySeverity(severity).attributesKey.defaultAttributes
|
||||
}
|
||||
}
|
||||
|
||||
private data class DisplayedSeverity(
|
||||
val id: String,
|
||||
val severity: StoredSeverity,
|
||||
val textAttributes: TextAttributes? = null,
|
||||
) {
|
||||
constructor(
|
||||
severity: HighlightSeverity,
|
||||
registrar: SeverityRegistrar,
|
||||
) : this(
|
||||
id = severity.name,
|
||||
severity = StoredSeverity(severity),
|
||||
textAttributes = getTextAttributes(registrar, severity)
|
||||
)
|
||||
}
|
||||
|
||||
private val settingsService = service<LensSettingsState>()
|
||||
|
||||
private val allSeverities by lazy(LazyThreadSafetyMode.NONE) {
|
||||
val settings = settingsService.state
|
||||
val registrar = SeverityRegistrar.getSeverityRegistrar(null)
|
||||
|
||||
val knownSeverities = LensSeverityFilter.getSupportedSeverities(registrar).map { DisplayedSeverity(it, registrar) }
|
||||
val knownSeverityIds = knownSeverities.mapTo(HashSet(), DisplayedSeverity::id)
|
||||
|
||||
// Update names and priorities of stored severities.
|
||||
for ((id, knownSeverity, _) in knownSeverities) {
|
||||
val storedSeverity = settings.hiddenSeverities[id]
|
||||
if (storedSeverity != null && storedSeverity != knownSeverity) {
|
||||
settings.hiddenSeverities[id] = knownSeverity
|
||||
}
|
||||
}
|
||||
|
||||
val unknownSeverities = settings.hiddenSeverities.entries
|
||||
.filterNot { it.key in knownSeverityIds }
|
||||
.map { DisplayedSeverity(it.key, it.value) }
|
||||
|
||||
(knownSeverities + unknownSeverities).sortedByDescending { it.severity.priority }
|
||||
}
|
||||
|
||||
override fun getId(): String {
|
||||
return ID
|
||||
}
|
||||
|
||||
override fun createPanel(): DialogPanel {
|
||||
val settings = settingsService.state
|
||||
|
||||
return panel {
|
||||
group("Shown Severities") {
|
||||
for ((id, severity, textAttributes) in allSeverities) {
|
||||
row {
|
||||
checkBox(severity.name)
|
||||
.bindSelectedToNotIn(settings.hiddenSeverities, id, severity)
|
||||
.gap(RightGap.COLUMNS)
|
||||
|
||||
labelWithAttributes("Example", textAttributes)
|
||||
}.layout(RowLayout.PARENT_GRID)
|
||||
}
|
||||
|
||||
row {
|
||||
checkBox("Other").bindSelected(settings::showUnknownSeverities)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <K, V> Cell<JBCheckBox>.bindSelectedToNotIn(collection: MutableMap<K, V>, key: K, value: V): Cell<JBCheckBox> {
|
||||
return bindSelected({ key !in collection }, { if (it) collection.remove(key) else collection[key] = value })
|
||||
}
|
||||
|
||||
private fun Row.labelWithAttributes(text: String, textAttributes: TextAttributes?): Cell<SimpleRendererComponent> {
|
||||
val label = SimpleRendererComponent(null, null, true)
|
||||
label.setText(text, textAttributes, false)
|
||||
label.focusTraversalPolicy = DisabledTraversalPolicy()
|
||||
|
||||
val editor = label.editor
|
||||
editor.setCustomCursor(this, Cursor.getDefaultCursor())
|
||||
editor.contentComponent.setOpaque(false)
|
||||
editor.selectionModel.addSelectionListener(object : SelectionListener {
|
||||
override fun selectionChanged(e: SelectionEvent) {
|
||||
if (!e.newRange.isEmpty) {
|
||||
editor.selectionModel.removeSelection(true)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Disposer.register(disposable!!, label)
|
||||
return cell(label)
|
||||
}
|
||||
|
||||
override fun apply() {
|
||||
super.apply()
|
||||
settingsService.update()
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package com.chylex.intellij.inspectionlens.settings
|
||||
|
||||
import com.chylex.intellij.inspectionlens.InspectionLensRefresher
|
||||
import com.chylex.intellij.inspectionlens.editor.LensSeverityFilter
|
||||
import com.intellij.openapi.components.BaseState
|
||||
import com.intellij.openapi.components.SettingsCategory
|
||||
import com.intellij.openapi.components.SimplePersistentStateComponent
|
||||
import com.intellij.openapi.components.State
|
||||
import com.intellij.openapi.components.Storage
|
||||
import com.intellij.util.xmlb.annotations.XMap
|
||||
|
||||
@State(
|
||||
name = LensApplicationConfigurable.ID,
|
||||
storages = [ Storage("chylex.inspectionLens.xml") ],
|
||||
category = SettingsCategory.UI
|
||||
)
|
||||
class LensSettingsState : SimplePersistentStateComponent<LensSettingsState.State>(State()) {
|
||||
class State : BaseState() {
|
||||
@get:XMap
|
||||
val hiddenSeverities by map<String, StoredSeverity>()
|
||||
|
||||
var showUnknownSeverities by property(true)
|
||||
}
|
||||
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
var severityFilter = createSeverityFilter()
|
||||
private set
|
||||
|
||||
override fun loadState(state: State) {
|
||||
super.loadState(state)
|
||||
update()
|
||||
}
|
||||
|
||||
fun update() {
|
||||
severityFilter = createSeverityFilter()
|
||||
InspectionLensRefresher.scheduleRefresh()
|
||||
}
|
||||
|
||||
private fun createSeverityFilter(): LensSeverityFilter {
|
||||
val state = state
|
||||
return LensSeverityFilter(state.hiddenSeverities.keys, state.showUnknownSeverities)
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.chylex.intellij.inspectionlens.settings
|
||||
|
||||
import com.intellij.lang.annotation.HighlightSeverity
|
||||
import com.intellij.util.xmlb.annotations.Tag
|
||||
|
||||
@Tag("severity")
|
||||
data class StoredSeverity(var name: String = "", var priority: Int = 0) {
|
||||
constructor(severity: HighlightSeverity) : this(severity.displayCapitalizedName, severity.myVal)
|
||||
}
|
@ -4,19 +4,18 @@
|
||||
<vendor url="https://chylex.com">chylex</vendor>
|
||||
|
||||
<description><![CDATA[
|
||||
Shows errors, warnings, and other inspection highlights inline.
|
||||
Displays errors, warnings, and other inspections inline. Highlights the background of lines with inspections. Supports light and dark themes out of the box.
|
||||
<br><br>
|
||||
After installing the plugin, inspection descriptions will appear after the ends of lines, and the lines will be highlighted with a background color.
|
||||
Shown inspection severities are <b>Errors</b>, <b>Warnings</b>, <b>Weak Warnings</b>, <b>Server Problems</b>, <b>Grammar Errors</b>, <b>Typos</b>, and other inspections from plugins or future IntelliJ versions that have a high enough severity level.
|
||||
Each severity has a different color, with support for both light and dark themes.
|
||||
<br><br>
|
||||
Note: The plugin is not customizable outside the ability to disable/enable the plugin without restarting the IDE.
|
||||
If the defaults don't work for you, I recommend trying the <a href="https://plugins.jetbrains.com/plugin/17302-inlineerror">Inline Error</a> plugin which can be customized, building your own version of Inspection Lens, or proposing your change in the <a href="https://github.com/chylex/IntelliJ-Inspection-Lens/issues">issue tracker</a>.
|
||||
By default, the plugin shows <b>Errors</b>, <b>Warnings</b>, <b>Weak Warnings</b>, <b>Server Problems</b>, <b>Grammar Errors</b>, <b>Typos</b>, and other inspections with a high enough severity level. Configure visible severities in <b>Settings | Tools | Inspection Lens</a>.
|
||||
<br><br>
|
||||
Inspired by <a href="https://marketplace.visualstudio.com/items?itemName=usernamehw.errorlens">Error Lens</a> for VS Code, and <a href="https://plugins.jetbrains.com/plugin/17302-inlineerror">Inline Error</a> for IntelliJ Platform.
|
||||
]]></description>
|
||||
|
||||
<change-notes><![CDATA[
|
||||
<b>Version 1.4</b>
|
||||
<ul>
|
||||
<li>Added configuration of visible severities to <b>Settings | Tools | Inspection Lens</b>.</li>
|
||||
</ul>
|
||||
<b>Version 1.3.3</b>
|
||||
<ul>
|
||||
<li>Partially reverted fix for inspections that include HTML in their description due to breaking inspections with angled brackets.</li>
|
||||
@ -63,6 +62,14 @@
|
||||
<depends>com.intellij.modules.platform</depends>
|
||||
<depends optional="true" config-file="compatibility/InspectionLens-Grazie.xml">tanvd.grazi</depends>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<applicationService serviceImplementation="com.chylex.intellij.inspectionlens.settings.LensSettingsState" />
|
||||
<applicationConfigurable id="com.chylex.intellij.inspectionlens.settings.LensApplicationConfigurable"
|
||||
instance="com.chylex.intellij.inspectionlens.settings.LensApplicationConfigurable"
|
||||
displayName="Inspection Lens"
|
||||
parentId="tools" />
|
||||
</extensions>
|
||||
|
||||
<applicationListeners>
|
||||
<listener class="com.chylex.intellij.inspectionlens.InspectionLensPluginListener" topic="com.intellij.ide.plugins.DynamicPluginListener" />
|
||||
</applicationListeners>
|
||||
|
Loading…
Reference in New Issue
Block a user