Skip to content

Commit

Permalink
Finalise full test rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
FWDekker committed Sep 16, 2023
1 parent e9899b3 commit 62d5ef6
Show file tree
Hide file tree
Showing 50 changed files with 408 additions and 414 deletions.
9 changes: 7 additions & 2 deletions .config/detekt/.detekt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ complexity:
# [False Positive] Solved using resource bundles. All remaining duplicates are resource identifiers.
StringLiteralDuplication:
active: false
# [Exception] Acceptable for helper files.
TooManyFunctions:
excludes: '**/*Helper.kt'

formatting:
# [Disagree] Acceptable for many short arguments.
Expand All @@ -39,6 +42,9 @@ formatting:
# [Disagree] Consecutive blank lines are used consistently to group blocks of code.
NoConsecutiveBlankLines:
active: false
# [Disagree] Required for lists and varargs, but ugly when it is unlikely that the function signature will change.
TrailingCommaOnCallSite:
active: false

potential-bugs:
# [Exception] Initialised by scene builder.
Expand All @@ -63,8 +69,7 @@ style:
active: false
# [Exception] Acceptable in (parameterized) tests.
DestructuringDeclarationWithTooManyEntries:
excludes:
- '**/test/**'
excludes: '**/test/**'
# [Bug] Fails when used as function expression body.
MultilineRawStringIndentation:
active: false
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ See [Plugin Signing](https://plugins.jetbrains.com/docs/intellij/plugin-signing.
### 🧪 Quality assurance
```bash
$ gradlew test # Run tests
$ gradlew test --tests X # Run tests in class X
$ gradlew test --tests X # Run tests in class X (package name optional)
$ gradlew check # Run tests and static analysis
$ gradlew runPluginVerifier # Check for compatibility issues
```
Expand Down
15 changes: 13 additions & 2 deletions src/main/kotlin/com/fwdekker/randomness/Bundle.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ object Bundle {
*
* @throws java.util.MissingFormatArgumentException if [args] has fewer arguments than required for [format]
*/
// TODO: Simplify documentation everywhere throughout the project to remove redundant `@param` specifications
fun String.matchesFormat(format: String, vararg args: String) =
Regex(format.format(*args).replace(Regex("%[0-9]+\\\$[Ss]"), ".*")).matches(this)
// TODO: Simplify documentation everywhere throughout the project to remove redundant `@param` specifications
Regex("%[0-9]+\\\$[Ss]").findAll(format)
.toList()
.reversed()
.fold(format) { acc, match ->
if (match.value.drop(1).dropLast(2).toInt() > args.size)
acc.replaceRange(match.range, ".*")
else
acc
}
.format(*args)
.let { Regex(it) }
.matches(this)
5 changes: 3 additions & 2 deletions src/main/kotlin/com/fwdekker/randomness/SchemeEditor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import javax.swing.JComponent
* An editor for a [Scheme].
*
* @param S the type of scheme edited in this editor
* @param scheme the scheme edited in this editor
* @property scheme the scheme edited in this editor
*/
abstract class SchemeEditor<S : Scheme>(val scheme: S) : Disposable {
/**
Expand Down Expand Up @@ -70,12 +70,13 @@ abstract class SchemeEditor<S : Scheme>(val scheme: S) : Disposable {
*
* @param listener the function to invoke on every change in this editor
*/
@Suppress("detekt:SpreadOperator") // Acceptable because this method is called rarely
fun addChangeListener(listener: () -> Unit) =
addChangeListenerTo(*(components + decoratorEditors).toTypedArray(), listener = listener)


/**
* Disposes of this editor's resources.
* Disposes this editor's resources.
*/
override fun dispose() = Disposer.dispose(this)
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ data class DecimalScheme(
/**
* The default value of the [showTrailingZeroes] field.
*/
const val DEFAULT_SHOW_TRAILING_ZEROES = true
const val DEFAULT_SHOW_TRAILING_ZEROES = false

/**
* The preset values for the [decimalSeparator] field.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ data class Template(
WordScheme::class,
]
)
val schemes: MutableList<Scheme> = DEFAULT_SCHEMES,
var schemes: MutableList<Scheme> = DEFAULT_SCHEMES,
val arrayDecorator: ArrayDecorator = DEFAULT_ARRAY_DECORATOR,
) : Scheme() {
override val typeIcon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,20 @@ import com.intellij.openapi.actionSystem.impl.DynamicActionConfigurationCustomiz


/**
* Registers and unregisters actions for the user's [Template]s so that they can be inserted using shortcuts.
* Registers, replaces, and unregisters actions for the user's [Template]s so that they can be inserted using shortcuts.
*
* @property getTemplates shorthand to return all the user's stored [Template]s
*/
class TemplateActionLoader : DynamicActionConfigurationCustomizer {
/**
* Shorthand to return all the user's stored [Template]s.
*/
private val templates: List<Template> get() = PersistentSettings.default.state.templates


open class TemplateActionLoader(
private val getTemplates: () -> List<Template> = { PersistentSettings.default.state.templates },
) : DynamicActionConfigurationCustomizer {
/**
* Registers the actions for all [Template]s in the user's [PersistentSettings].
*
* @param actionManager the manager to register actions through
*/
override fun registerActions(actionManager: ActionManager) {
templates.forEach { registerAction(actionManager, it) }
getTemplates().forEach { registerAction(actionManager, it) }
}

/**
Expand All @@ -30,7 +28,7 @@ class TemplateActionLoader : DynamicActionConfigurationCustomizer {
* @param actionManager the manager to unregister actions through
*/
override fun unregisterActions(actionManager: ActionManager) {
templates.forEach { unregisterAction(actionManager, it) }
getTemplates().forEach { unregisterAction(actionManager, it) }
}


Expand All @@ -39,23 +37,15 @@ class TemplateActionLoader : DynamicActionConfigurationCustomizer {
*
* @param oldList the list of stored [Template]s before storing [newList]
* @param newList the list of stored [Template]s after storing them
* @param actionManager the manager with which actions are (de)registered
*/
fun updateActions(oldList: Set<Template>, newList: Set<Template>) {
val actionManager = ActionManager.getInstance()

val newUuids = newList.map { it.uuid }
oldList.filterNot { it.uuid in newUuids }.forEach {
// TODO: Remove ALL actions, not just the one with `actionId`?
if (actionManager.getAction(it.actionId) != null)
actionManager.unregisterAction(it.actionId)
}

newList.forEach {
if (actionManager.getAction(it.actionId) == null)
registerAction(actionManager, it)
else
replaceAction(actionManager, it)
}
fun updateActions(
oldList: List<Template>,
newList: List<Template>,
actionManager: ActionManager = ActionManager.getInstance(),
) {
oldList.filterNot { it in newList }.forEach { unregisterAction(actionManager, it) }
newList.forEach { registerAction(actionManager, it) }
}


Expand All @@ -82,8 +72,10 @@ class TemplateActionLoader : DynamicActionConfigurationCustomizer {
*/
private fun registerAction(actionManager: ActionManager, template: Template) =
getActions(template).forEach { (actionId, action) ->
actionManager.registerAction(actionId, action)
actionManager.replaceAction(actionId, action)
if (actionManager.getAction(actionId) == null)
actionManager.registerAction(actionId, action)
else
actionManager.replaceAction(actionId, action)
}

/**
Expand All @@ -94,13 +86,9 @@ class TemplateActionLoader : DynamicActionConfigurationCustomizer {
*/
private fun unregisterAction(actionManager: ActionManager, template: Template) =
getActions(template).forEach { (actionId, _) -> actionManager.unregisterAction(actionId) }

/**
* Replaces the actions associated with [template].
*
* @param actionManager the manager to replace actions through
* @param template the [Template] to replace actions for
*/
private fun replaceAction(actionManager: ActionManager, template: Template) =
getActions(template).forEach { (actionId, action) -> actionManager.replaceAction(actionId, action) }
}

/**
* Constructor-less version of [TemplateActionLoader], as is required in `plugin.xml`.
*/
class DefaultTemplateActionLoader : TemplateActionLoader()
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,11 @@ class TemplateInsertAction(

/**
* Returns the component that the [editor] prefers to be focused when the editor is focused.
*
* @return the component that the [editor] prefers to be focused when the editor is focused.
*/
override fun getPreferredFocusedComponent() = editor.preferredFocusedComponent

/**
* Creates a component containing the [editor] and the [previewPanel].
*
* @return a component containing the [editor] and the [previewPanel]
*/
override fun createComponent() =
JPanel(BorderLayout())
Expand All @@ -163,9 +159,7 @@ class TemplateInsertAction(
}

/**
* Returns `true`
*
* @return `true`
* Returns `true`.
*/
override fun isModified() = true

Expand All @@ -176,8 +170,6 @@ class TemplateInsertAction(

/**
* Returns [text].
*
* @return [text]
*/
override fun getDisplayName() = text

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ import kotlin.math.min
/**
* A tree containing [Template]s and [Scheme]s.
*
* The tree contains the templates and schemes defined in the [TemplateList] of [currentSettings] by loading that list into
* this tree's [TemplateJTreeModel]. Furthermore, when a new [Scheme] is added or copied, it will use the
* The tree contains the templates and schemes defined in the [TemplateList] of [currentSettings] by loading that list
* into this tree's [TemplateJTreeModel]. Furthermore, when a new [Scheme] is added or copied, it will use the
* [currentSettings].
*
* This tree reads from [originalSettings] to determine whether particular [Scheme]s have been modified. Modified [Scheme]s
* can be reset, in which case the original state is copied into that scheme in the [currentSettings].
* This tree reads from [originalSettings] to determine whether particular [Scheme]s have been modified. Modified
* [Scheme]s can be reset, in which case the original state is copied into that scheme in the [currentSettings].
*
* @property originalSettings The original settings before any modifications were made.
* @property currentSettings The current settings which include modifications.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,21 +87,24 @@ class TemplateJTreeModel(list: TemplateList = TemplateList(mutableListOf())) : T
/**
* Not implemented because this method is used only if this is a model for a table.
*
* @throws NotImplementedError always
* @throws UnsupportedOperationException always
*/
@Throws(NotImplementedError::class)
override fun addRow() = throw NotImplementedError(Bundle("template_list.error.add_empty_row"))
@Throws(UnsupportedOperationException::class)
override fun addRow() =
throw UnsupportedOperationException(Bundle("template_list.error.add_empty_row"))

/**
* Not implemented because this method is used only if this is a model for a table.
*
* @throws NotImplementedError always
* @throws UnsupportedOperationException always
*/
@Throws(NotImplementedError::class)
override fun removeRow(index: Int) = throw NotImplementedError(Bundle("template_list.error.remove_row_by_index"))
@Throws(UnsupportedOperationException::class)
override fun removeRow(index: Int) =
throw UnsupportedOperationException(Bundle("template_list.error.remove_row_by_index"))

/**
* Moves the node at row [oldIndex] to row [newIndex], and expands and selects the moved node.
* Exchanges two consecutive rows, moving the node at row [oldIndex] to row [newIndex], and expands and selects the
* moved node.
*
* Indices are looked up using [rowToNode], and are typically relative to the current expansion state of the view.
*
Expand Down Expand Up @@ -396,11 +399,11 @@ class TemplateJTreeModel(list: TemplateList = TemplateList(mutableListOf())) : T
/**
* Not implemented because this model does not contain an editor component.
*
* @throws NotImplementedError always
* @throws UnsupportedOperationException always
*/
@Throws(NotImplementedError::class)
@Throws(UnsupportedOperationException::class)
override fun valueForPathChanged(path: TreePath, newValue: Any) =
throw NotImplementedError(Bundle("template_list.error.change_value_by_path"))
throw UnsupportedOperationException(Bundle("template_list.error.change_value_by_path"))

/**
* Adds [listener] as a listener.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class TemplateListConfigurable : Configurable {
/**
* The user interface for changing the settings, displayed in IntelliJ's settings window.
*/
@Suppress("detekt:LateinitUsage") // Initialized in `createComponent`
lateinit var editor: TemplateListEditor private set

/**
Expand Down Expand Up @@ -57,7 +58,7 @@ class TemplateListConfigurable : Configurable {
override fun reset() = editor.reset()

/**
* Disposes of the configurable's resources.
* Disposes the configurable's resources.
*/
override fun disposeUIResources() {
editor.dispose()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import javax.swing.SwingUtilities
*
* Though this editor only changes [TemplateList]s, it still maintains a reference to
*
* @param originalSettings the settings containing the templates to edit
* @property originalSettings the settings containing the templates to edit
* @see TemplateListConfigurable
*/
class TemplateListEditor(private val originalSettings: Settings = Settings.DEFAULT) : Disposable {
Expand Down Expand Up @@ -182,9 +182,9 @@ class TemplateListEditor(private val originalSettings: Settings = Settings.DEFAU
* Does nothing if and only if [isModified] returns `false`.
*/
fun applyState() {
val oldList = originalSettings.templates.toSet()
val oldList = originalSettings.templates
originalSettings.copyFrom(readState())
val newList = originalSettings.templates.toSet()
val newList = originalSettings.templates

TemplateActionLoader().updateActions(oldList, newList)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ data class TemplateReference(
templateUuid == null -> Bundle("reference.error.no_selection")
template == null -> Bundle("reference.error.not_found")
recursion != null -> Bundle("reference.error.recursion", "(${recursion.joinToString("") { it.name }})")
else -> arrayDecorator.doValidate()
else -> affixDecorator.doValidate() ?: arrayDecorator.doValidate()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class JDateTimeField(
private val default: LocalDateTime = LocalDateTime.now(),
) : JFormattedTextField(DateTimeFormatter()) {
/**
* The current [value] represented as a [Long].
* The current [value] represented as a [Long] of the millisecond epoch.
*/
var longValue: Long
get() = value.toEpochMilli()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.fwdekker.randomness.ui

import com.fwdekker.randomness.Bundle
import java.text.DecimalFormatSymbols
import java.util.Locale
import javax.swing.JComponent
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/fwdekker/randomness/ui/PreviewPanel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class PreviewPanel(private val getScheme: () -> Scheme) : Disposable {
}

/**
* Disposes of this panel's resources, to be used when this panel is no longer used.
* Disposes this panel's resources, to be used when this panel is no longer used.
*/
override fun dispose() = Disposer.dispose(this)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class WordSchemeEditor(scheme: WordScheme = WordScheme()) : SchemeEditor<WordSch
.withFixedHeight(UIConstants.SIZE_VERY_LARGE)
.bind(
{ document.getWordList() },
{ _, it: List<String> -> document.setWordList(it) },
{ _, list: List<String> -> document.setWordList(list) },
scheme::words.toMutableProperty()
)
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
displayName="Randomness" />

<!-- Dynamically loads, unloads, and updates template actions -->
<dynamicActionConfigurationCustomizer implementation="com.fwdekker.randomness.template.TemplateActionLoader" />
<dynamicActionConfigurationCustomizer
implementation="com.fwdekker.randomness.template.DefaultTemplateActionLoader" />
</extensions>

<!-- Non-dynamic actions -->
Expand Down
Loading

0 comments on commit 62d5ef6

Please sign in to comment.