mirror of
https://github.com/chylex/IntelliJ-Inspection-Lens.git
synced 2024-11-25 07:42:58 +01:00
Compare commits
No commits in common. "e28804ad5d03836b30d23c91b7fd753772bb3c65" and "223fceb6b91622cbdf3de43295af81fa8e5af0c1" have entirely different histories.
e28804ad5d
...
223fceb6b9
@ -1,8 +1,10 @@
|
|||||||
# Inspection Lens <img align="right" src="logo.png" alt="Plugin Logo">
|
# Inspection Lens <img align="right" src="logo.png" alt="Plugin Logo">
|
||||||
|
|
||||||
Displays errors, warnings, and other inspections inline. Highlights the background of lines with inspections. Supports light and dark themes out of the box.
|
IntelliJ plugin that shows errors, warnings, and other inspection highlights inline.
|
||||||
|
|
||||||
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**.
|
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).
|
||||||
|
|
||||||
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.
|
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"
|
group = "com.chylex.intellij.inspectionlens"
|
||||||
version = "1.4"
|
version = "1.3.3"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -83,12 +83,6 @@ class EditorLensManager private constructor(private val editor: Editor) {
|
|||||||
lensManager.hide(highlighter)
|
lensManager.hide(highlighter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object HideAll : Command {
|
|
||||||
override fun apply(lensManager: EditorLensManager) {
|
|
||||||
lensManager.hideAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,10 +15,6 @@ class EditorLensManagerDispatcher(private val lensManager: EditorLensManager) {
|
|||||||
enqueue(EditorLensManager.Command.Hide(highlighter))
|
enqueue(EditorLensManager.Command.Hide(highlighter))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideAll() {
|
|
||||||
enqueue(EditorLensManager.Command.HideAll)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun enqueue(item: EditorLensManager.Command) {
|
private fun enqueue(item: EditorLensManager.Command) {
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
queuedItems.add(item)
|
queuedItems.add(item)
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package com.chylex.intellij.inspectionlens.editor
|
package com.chylex.intellij.inspectionlens.editor
|
||||||
|
|
||||||
import com.chylex.intellij.inspectionlens.settings.LensSettingsState
|
|
||||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
import com.intellij.codeInsight.daemon.impl.HighlightInfo
|
||||||
|
import com.intellij.lang.annotation.HighlightSeverity
|
||||||
import com.intellij.openapi.Disposable
|
import com.intellij.openapi.Disposable
|
||||||
import com.intellij.openapi.components.service
|
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.editor.ex.MarkupModelEx
|
import com.intellij.openapi.editor.ex.MarkupModelEx
|
||||||
import com.intellij.openapi.editor.ex.RangeHighlighterEx
|
import com.intellij.openapi.editor.ex.RangeHighlighterEx
|
||||||
@ -49,16 +48,12 @@ internal class LensMarkupModelListener private constructor(editor: Editor) : Mar
|
|||||||
highlighters.forEach(::showIfValid)
|
highlighters.forEach(::showIfValid)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hideAll() {
|
|
||||||
lensManagerDispatcher.hideAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val EDITOR_KEY = Key<LensMarkupModelListener>(LensMarkupModelListener::class.java.name)
|
private val EDITOR_KEY = Key<LensMarkupModelListener>(LensMarkupModelListener::class.java.name)
|
||||||
private val SETTINGS_SERVICE = service<LensSettingsState>()
|
private val MINIMUM_SEVERITY = HighlightSeverity.TEXT_ATTRIBUTES.myVal + 1
|
||||||
|
|
||||||
private fun getFilteredHighlightInfo(highlighter: RangeHighlighter): HighlightInfo? {
|
private fun getFilteredHighlightInfo(highlighter: RangeHighlighter): HighlightInfo? {
|
||||||
return HighlightInfo.fromRangeHighlighter(highlighter)?.takeIf { SETTINGS_SERVICE.severityFilter.test(it.severity) }
|
return HighlightInfo.fromRangeHighlighter(highlighter)?.takeIf { it.severity.myVal >= MINIMUM_SEVERITY }
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun runWithHighlighterIfValid(highlighter: RangeHighlighter, actionForImmediate: (HighlighterWithInfo) -> Unit, actionForAsync: (HighlighterWithInfo.Async) -> Unit) {
|
private inline fun runWithHighlighterIfValid(highlighter: RangeHighlighter, actionForImmediate: (HighlighterWithInfo) -> Unit, actionForAsync: (HighlighterWithInfo.Async) -> Unit) {
|
||||||
@ -106,7 +101,6 @@ internal class LensMarkupModelListener private constructor(editor: Editor) : Mar
|
|||||||
val listener = editor.getUserData(EDITOR_KEY) ?: return
|
val listener = editor.getUserData(EDITOR_KEY) ?: return
|
||||||
val markupModel = getMarkupModel(editor) ?: return
|
val markupModel = getMarkupModel(editor) ?: return
|
||||||
|
|
||||||
listener.hideAll()
|
|
||||||
listener.showAllValid(markupModel.allHighlighters)
|
listener.showAllValid(markupModel.allHighlighters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,127 +0,0 @@
|
|||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
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,18 +4,19 @@
|
|||||||
<vendor url="https://chylex.com">chylex</vendor>
|
<vendor url="https://chylex.com">chylex</vendor>
|
||||||
|
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
Displays errors, warnings, and other inspections inline. Highlights the background of lines with inspections. Supports light and dark themes out of the box.
|
Shows errors, warnings, and other inspection highlights inline.
|
||||||
<br><br>
|
<br><br>
|
||||||
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>.
|
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>.
|
||||||
<br><br>
|
<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.
|
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>
|
]]></description>
|
||||||
|
|
||||||
<change-notes><![CDATA[
|
<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>
|
<b>Version 1.3.3</b>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Partially reverted fix for inspections that include HTML in their description due to breaking inspections with angled brackets.</li>
|
<li>Partially reverted fix for inspections that include HTML in their description due to breaking inspections with angled brackets.</li>
|
||||||
@ -62,14 +63,6 @@
|
|||||||
<depends>com.intellij.modules.platform</depends>
|
<depends>com.intellij.modules.platform</depends>
|
||||||
<depends optional="true" config-file="compatibility/InspectionLens-Grazie.xml">tanvd.grazi</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>
|
<applicationListeners>
|
||||||
<listener class="com.chylex.intellij.inspectionlens.InspectionLensPluginListener" topic="com.intellij.ide.plugins.DynamicPluginListener" />
|
<listener class="com.chylex.intellij.inspectionlens.InspectionLensPluginListener" topic="com.intellij.ide.plugins.DynamicPluginListener" />
|
||||||
</applicationListeners>
|
</applicationListeners>
|
||||||
|
Loading…
Reference in New Issue
Block a user