From 3e0ea38ce62eb30632d2aa93087af8a6b59f27a3 Mon Sep 17 00:00:00 2001 From: redcatbaer Date: Sat, 27 Jun 2026 14:03:25 +0200 Subject: [PATCH 1/9] #37: Added run configuration templates to specification. --- doc/design/building_block_view.md | 21 ++-- doc/design/runtime_view.md | 79 ++++++-------- doc/system_requirements.md | 168 +++++++++++++----------------- 3 files changed, 116 insertions(+), 152 deletions(-) diff --git a/doc/design/building_block_view.md b/doc/design/building_block_view.md index bb5d264..d61f529 100644 --- a/doc/design/building_block_view.md +++ b/doc/design/building_block_view.md @@ -238,29 +238,28 @@ Covers: Needs: bld, itest ### Trace Configuration Integration -`dsn~trace-configuration-integration~1` +`dsn~trace-configuration-integration~2` -The plugin provides a trace-configuration component that stores OpenFastTrace trace-scope settings per IntelliJ project and through dedicated run configurations. It exposes those settings through project configuration UI and the run configuration editor, resolves the selected-resource options and filters into a normalized OpenFastTrace input set and filter criteria, stores the run-configuration result-view selection, treats the IntelliJ Test Runner UI as the result-view default when no selection is stored, and owns the plugin resource used as the OpenFastTrace run-configuration icon. +The plugin provides a trace-configuration component that stores OpenFastTrace trace-scope settings per IntelliJ project and through dedicated run configurations. It provides pre-configured templates for common scanning scenarios. It exposes those settings through project configuration UI and the run configuration editor, resolves the selected-resource options and filters into a normalized OpenFastTrace input set and filter criteria, stores the run-configuration result-view selection, treats the IntelliJ Test Runner UI as the result-view default when no selection is stored, and owns the plugin resource used as the OpenFastTrace run-configuration icon. Covers: - `scn~test-runner-as-default-run-configuration-result-view~1` - `scn~select-plain-text-trace-result-view~1` - `scn~select-test-runner-trace-result-view~1` - `scn~show-openfasttrace-icon-for-run-configurations~1` +- `scn~use-run-configuration-templates~1` Needs: impl, itest ### Trace Action Integration -`dsn~trace-action-integration~2` +`dsn~trace-action-integration~3` -The plugin provides a trace-action component that contributes an `OpenFastTrace` action group with a `Trace Project` action under the global `Tools` menu. This component is responsible for exposing the entry only in an opened project context and for handing the action invocation to trace-configuration resolution, trace execution, and the default IntelliJ Test Runner UI presentation. +The plugin provides a trace-action component that is responsible for handing the trace invocation to trace-configuration resolution, trace execution, and the default IntelliJ Test Runner UI presentation. Covers: -- `scn~show-trace-project-action-in-tools-menu~1` -- `scn~disable-trace-project-action-without-open-project~1` -- `scn~run-trace-project-in-background~1` -- `scn~show-trace-project-in-test-runner-ui-by-default~1` -- `scn~reject-trace-project-without-valid-project-path~1` +- `scn~run-trace-project-in-background~2` +- `scn~show-trace-result-in-test-runner-ui-by-default~2` +- `scn~reject-trace-without-valid-project-path~1` Needs: impl, itest @@ -272,9 +271,9 @@ The plugin provides a trace-execution service that accepts the effective OpenFas Because OpenFastTrace discovers importers and reporters through Java `ServiceLoader`, this service executes OFT import and report-rendering calls with the plugin class loader as the thread context class loader and restores the previous context loader afterward. Covers: -- `scn~run-trace-project-in-background~1` +- `scn~run-trace-project-in-background~2` - `scn~trace-selected-project-resources~1` -- `scn~reject-trace-project-without-valid-project-path~1` +- `scn~reject-trace-without-valid-project-path~1` - `scn~show-successful-trace-output-in-ide-output-window~2` - `scn~show-resolved-trace-inputs-in-trace-output-window~1` - `scn~show-failing-trace-output-in-ide-output-window~1` diff --git a/doc/design/runtime_view.md b/doc/design/runtime_view.md index 3e2321e..5d5fbfa 100644 --- a/doc/design/runtime_view.md +++ b/doc/design/runtime_view.md @@ -350,58 +350,34 @@ Covers: Needs: impl, itest -## Trace Project - -### Show Trace Project Action in Tools Menu -`dsn~show-trace-project-action-in-tools-menu~1` - -**Given** the plugin is loaded into the IDE and an IntelliJ project is open -**When** the IDE builds the global `Tools` menu -**Then** the plugin contributes an `OpenFastTrace` action group that contains the `Trace Project` action. - -Covers: -- `scn~show-trace-project-action-in-tools-menu~1` - -Needs: impl, itest - -### Disable Trace Project Action without Open Project -`dsn~disable-trace-project-action-without-open-project~1` - -**Given** the plugin is loaded into the IDE and no IntelliJ project is open -**When** the IDE updates the presentation of the `Trace Project` action -**Then** the trace-action component disables that action instead of offering a runnable trace command. - -Covers: -- `scn~disable-trace-project-action-without-open-project~1` - -Needs: impl, itest +## Trace Execution ### Run Trace Project in Background -`dsn~run-trace-project-in-background~1` +`dsn~run-trace-project-in-background~2` **Given** an IntelliJ project is open and its base directory resolves to a valid local file-system path -**When** a user invokes `Tools | OpenFastTrace | Trace Project` -**Then** the trace-action component starts a background task, the trace-configuration component resolves the effective OpenFastTrace inputs for the project, the trace-execution service invokes the OpenFastTrace library for those inputs, and the IDE keeps the editor UI responsive while showing progress for the running trace. +**When** a user starts an OpenFastTrace trace +**Then** the trace component starts a background task, the trace-configuration component resolves the effective OpenFastTrace inputs for the project, the trace-execution service invokes the OpenFastTrace library for those inputs, and the IDE keeps the editor UI responsive while showing progress for the running trace. Covers: -- `scn~run-trace-project-in-background~1` +- `scn~run-trace-project-in-background~2` Needs: impl, itest -### Show Trace Project in Test Runner UI by Default -`dsn~show-trace-project-in-test-runner-ui-by-default~1` +### Show Trace Result in Test Runner UI by Default +`dsn~show-trace-result-in-test-runner-ui-by-default~2` -**Given** the global `Trace Project` action receives a valid OpenFastTrace trace result -**When** the trace-action flow presents that result -**Then** it creates an IntelliJ Test Runner UI console, maps the structured OpenFastTrace trace to SM test runner nodes, and shows that console as the default run content for the action. +**Given** an OpenFastTrace trace receives a valid trace result +**When** the trace flow presents that result +**Then** it creates an IntelliJ Test Runner UI console, maps the structured OpenFastTrace trace to SM test runner nodes, and shows that console as the default run content. Covers: -- `scn~show-trace-project-in-test-runner-ui-by-default~1` +- `scn~show-trace-result-in-test-runner-ui-by-default~2` Needs: impl, itest ### Configure Trace Scope in Project Settings -`dsn~configure-trace-scope-in-project-settings~1` +`dsn~configure-trace-scope-in-project-settings~2` **Given** an IntelliJ project is open **When** a user opens the OpenFastTrace project settings @@ -413,10 +389,10 @@ Covers: Needs: impl, itest ### Trace Selected Project Resources -`dsn~trace-selected-project-resources~1` +`dsn~trace-selected-project-resources~2` -**Given** an IntelliJ project is open and OpenFastTrace project settings are configured for selected-resource tracing -**When** a user invokes `Tools | OpenFastTrace | Trace Project` +**Given** an IntelliJ project is open and OpenFastTrace project settings or run configuration are configured for selected-resource tracing +**When** a user starts an OpenFastTrace trace **Then** the trace-configuration component resolves only the configured source roots, test roots, and additional project-relative paths and the trace-execution service passes only those inputs to OpenFastTrace. Covers: @@ -472,23 +448,34 @@ Covers: Needs: impl, itest -### Reject Trace Project without Valid Project Path -`dsn~reject-trace-project-without-valid-project-path~2` +### Reject Trace without Valid Project Path +`dsn~reject-trace-without-valid-project-path~1` **Given** an IntelliJ project is open but its base directory is missing, invalid, or not usable as a local OpenFastTrace input path -**When** a user invokes `Tools | OpenFastTrace | Trace Project` -**Then** the trace-action flow stops before starting the background trace run and reports the invalid project-path or configured-input condition through the IDE-visible trace flow. +**When** a user starts an OpenFastTrace trace +**Then** the trace flow stops before starting the background trace run and reports the invalid project-path or configured-input condition through the IDE-visible trace flow. + +Covers: +- `scn~reject-trace-without-valid-project-path~1` + +Needs: impl, itest + +### Use Run Configuration Templates +`dsn~use-run-configuration-templates~1` + +**When** a user creates a new OpenFastTrace run configuration from a template +**Then** the `OftRunConfigurationFactory` that matches the selected template creates a new `OftRunConfiguration` and initializes it with the pre-defined template settings. Covers: -- `scn~reject-trace-project-without-valid-project-path~1` +- `scn~use-run-configuration-templates~1` Needs: impl, itest ### OpenFastTrace Run Configuration -`dsn~openfasttrace-run-configuration~1` +`dsn~openfasttrace-run-configuration~2` **When** a user creates or edits an OpenFastTrace run configuration -**Then** the plugin uses the IntelliJ Run Configuration API (type, factory, configuration) to persist the name, scope, additional paths, artifact type filters, and tag filters. +**Then** the plugin uses the IntelliJ Run Configuration API (type, factory, configuration) to persist the name, scope, additional paths, artifact type filters, and tag filters. The plugin registers multiple factories to provide pre-configured templates for common scanning scenarios. Covers: - `scn~create-and-run-openfasttrace-run-configuration~1` diff --git a/doc/system_requirements.md b/doc/system_requirements.md index dc8fbfd..492e33e 100644 --- a/doc/system_requirements.md +++ b/doc/system_requirements.md @@ -38,7 +38,7 @@ A requirement tracing suite that uses specification documents and coverage marke ### Plugin -The OpenFastTrace IntelliJ plugin described by this specification. +The OpenFastTrace IntelliJ plug-in described by this specification. ### RST @@ -110,16 +110,16 @@ The plugin suggests existing OpenFastTrace specification item IDs while users fi Needs: req ### Run OFT Trace -`feat~run-oft-trace~2` +`feat~run-oft-trace~3` -The plugin lets users run an OpenFastTrace trace for the currently opened IntelliJ project and inspect the result inside the IDE using the IntelliJ Test Runner UI as the default view for the global project trace. +The plugin lets users run an OpenFastTrace trace for an IntelliJ project and inspect the result inside the IDE using the IntelliJ Test Runner UI or plain text output. Needs: req ### OFT Run Configurations -`feat~oft-run-configurations~1` +`feat~oft-run-configurations~2` -The plugin lets users define multiple OpenFastTrace run configurations with different scan parameters and filters. +The plugin lets users define multiple OpenFastTrace run configurations with different scan parameters and filters. It provides pre-configured templates for common scanning scenarios. Needs: req @@ -334,47 +334,23 @@ Needs: scn The following requirements refine the Run OFT Trace feature into user-visible capabilities. -### Show Trace Project Action in Tools Menu -`req~show-trace-project-action-in-tools-menu~1` - -The plugin adds an `OpenFastTrace` group with a `Trace Project` action to the global `Tools` menu. Users can find the trace entry in the established IDE location for project-level tooling actions. - -Covers: -- `feat~run-oft-trace~2` - -Needs: scn - -### Disable Trace Project Action without Open Project -`req~disable-trace-project-action-without-open-project~1` - -The plugin disables the `Trace Project` action when no IntelliJ project is open. - -Rationale: - -Users cannot invoke the trace action when the IDE has no project context to trace. - -Covers: -- `feat~run-oft-trace~2` - -Needs: scn - ### Trace Open Project from Project Root `req~trace-open-project-from-project-root~1` -The plugin traces the currently opened IntelliJ project by using the opened project directory as the default OpenFastTrace input root. Users can run a whole-project trace without manually selecting files and directories first. +The plugin can trace an IntelliJ project by using the project directory as the default OpenFastTrace input root. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` Needs: scn ### Configure Trace Scope in Project Settings `req~configure-trace-scope-in-project-settings~1` -The plugin integrates OpenFastTrace trace-scope settings into IntelliJ project configuration. Users can configure whether the `Trace Project` action traces the whole opened project or only selected resources and can edit the selected-resource paths directly in the IDE settings workflow. +The plugin integrates OpenFastTrace trace-scope settings into IntelliJ project configuration. Users can configure whether a trace uses the whole project or only selected resources and can edit the selected-resource paths directly in the IDE settings workflow. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` Needs: scn @@ -384,7 +360,7 @@ Needs: scn The plugin can trace selected project resources instead of the whole opened project directory. Users can restrict the OpenFastTrace scan to the resources they intend to include in the trace. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` Needs: scn @@ -394,7 +370,7 @@ Needs: scn When selected-resource tracing is active, the plugin can include source directories known to IntelliJ in the effective OpenFastTrace input set. Users do not need to discover and configure ordinary source roots by hand. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` Needs: scn @@ -404,7 +380,7 @@ Needs: scn When selected-resource tracing is active, the plugin can include test directories known to IntelliJ in the effective OpenFastTrace input set. Users do not need to discover and configure ordinary test roots by hand. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` Needs: scn @@ -414,7 +390,7 @@ Needs: scn When selected-resource tracing is active, the plugin lets users add additional trace inputs through a multi-line text field in the project settings. Each non-empty line specifies one file or directory path relative to the opened project directory that OpenFastTrace should scan. If the user has not changed that setting, the field contains exactly one default entry: `doc/`. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` Needs: scn @@ -424,17 +400,17 @@ Needs: scn The plugin runs the OpenFastTrace project trace in a background task with IDE progress reporting. Users can start a trace without blocking the editor UI while the trace is running. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` Needs: scn -### Show Trace Project in Test Runner UI by Default -`req~show-trace-project-in-test-runner-ui-by-default~1` +### Show Trace Result in Test Runner UI by Default +`req~show-trace-result-in-test-runner-ui-by-default~2` -When a user starts the global `Trace Project` action from the `Tools` menu, the plugin shows the default trace result in IntelliJ's Test Runner UI. Users can inspect the default project trace as structured source-file suites, specification-item tests, and trace-link sub-tests without creating a run configuration first. +The plugin shows the trace result in IntelliJ's Test Runner UI by default. Users can inspect the project trace as structured source-file suites, specification-item tests, and trace-link sub-tests. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` - `feat~oft-test-runner-trace-results~1` Needs: scn @@ -445,8 +421,8 @@ Needs: scn The plugin can show the OpenFastTrace text trace output in an IDE output sub-window and keep that output available after the trace finishes. Users who select the plain text result view can inspect the plain text result inside the IDE without looking at log files or an external terminal. Covers: -- `feat~run-oft-trace~2` -- `feat~oft-run-configurations~1` +- `feat~run-oft-trace~3` +- `feat~oft-run-configurations~2` Needs: scn @@ -456,7 +432,7 @@ Needs: scn The plugin makes OpenFastTrace specification item IDs in the trace output window navigable to their declarations in the opened project. Users can jump from a reported item in the trace output directly to the defining specification item without searching manually. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` Needs: scn @@ -466,7 +442,21 @@ Needs: scn The plugin provides a dedicated run configuration type for OpenFastTrace. Users can create, name, and save multiple trace configurations to switch quickly between different scan scopes and filters. Covers: -- `feat~oft-run-configurations~1` +- `feat~oft-run-configurations~2` + +Needs: scn + +### OpenFastTrace Run Configuration Templates +`req~openfasttrace-run-configuration-templates~1` + +The plugin provides pre-configured templates when creating new OpenFastTrace run configurations. These templates allow users to quickly set up common scanning scenarios. The following templates are available: +- **User requirements**: Scans `doc/`, excludes source directories, filters for artifact types: `feat, req, scn, bconstr`. +- **Design and down**: Scans `doc/`, excludes source directories, filters for artifact types: `feat, req, scn, bconstr, arch, dsn, constr`. +- **Typical project**: Scans `doc/` and all project source directories, with no artifact type filtering. +- **Unfiltered**: Scans the entire project (`.`) with no filters. + +Covers: +- `feat~oft-run-configurations~2` Needs: scn @@ -476,7 +466,7 @@ Needs: scn When using an OpenFastTrace run configuration, the plugin lets users filter the trace results by artifact types. Users can specify a comma-separated list of types (e.g., `req, dsn`) to focus the trace on specific document layers. Covers: -- `feat~oft-run-configurations~1` +- `feat~oft-run-configurations~2` Needs: scn @@ -486,7 +476,7 @@ Needs: scn When using an OpenFastTrace run configuration, the plugin lets users filter the trace results by tags. Users can specify a comma-separated list of tags to focus the trace on tagged specification items. Covers: -- `feat~oft-run-configurations~1` +- `feat~oft-run-configurations~2` Needs: scn @@ -500,7 +490,7 @@ Rationale: Users get structured trace inspection by default, while users who prefer the existing text report can opt into plain text output per run configuration. Covers: -- `feat~oft-run-configurations~1` +- `feat~oft-run-configurations~2` - `feat~oft-test-runner-trace-results~1` Needs: scn @@ -541,7 +531,7 @@ The following requirements refine how OpenFastTrace run configurations appear in The plugin shows an OpenFastTrace-specific icon for the `OpenFastTrace` run configuration type. Users can distinguish OpenFastTrace trace configurations from generic run actions in the run/debug UI. Covers: -- `feat~oft-run-configurations~1` +- `feat~oft-run-configurations~2` Needs: scn @@ -751,7 +741,7 @@ Needs: scn When a plain text project trace starts, the plugin writes the resolved project base directory that OpenFastTrace scans into the IDE output sub-window. Users can confirm the actual trace input root directly from the trace output. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` Needs: scn @@ -761,7 +751,7 @@ Needs: scn When a plain text project trace starts with selected-resource tracing, the plugin writes the resolved files and directories that it passes to OpenFastTrace into the IDE output sub-window. Users can confirm the actual configured trace scope directly from the trace output. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` Needs: scn @@ -771,7 +761,7 @@ Needs: scn The plugin reports when the opened project does not resolve to a valid local path before starting the trace. Users can see why the trace cannot start without inspecting plugin logs. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` Needs: scn @@ -781,7 +771,7 @@ Needs: scn When plain text output is selected, the plugin shows failing OpenFastTrace executions through the same IDE output flow as successful traces, including the text output and the failing result. Users can inspect trace failures without switching to plugin logs or an external terminal. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` Needs: scn @@ -791,7 +781,7 @@ Needs: scn The plugin preserves the OpenFastTrace plain-text defect summary for an unclean trace chain in the IDE output window, including the reported total-item count and defect count. Users can verify how many trace issues OpenFastTrace found directly from the text result. Covers: -- `feat~run-oft-trace~2` +- `feat~run-oft-trace~3` Needs: scn @@ -1158,35 +1148,11 @@ Needs: dsn The following scenarios describe the trace action flow for the opened IntelliJ project. -### Show Trace Project Action in Tools Menu -`scn~show-trace-project-action-in-tools-menu~1` - -**Given** the OpenFastTrace plugin is installed and an IntelliJ project is open -**When** a user opens the global `Tools` menu -**Then** the menu contains an `OpenFastTrace` group with a `Trace Project` action - -Covers: -- `req~show-trace-project-action-in-tools-menu~1` - -Needs: dsn - -### Disable Trace Project Action without Open Project -`scn~disable-trace-project-action-without-open-project~1` - -**Given** the OpenFastTrace plugin is installed and no IntelliJ project is open -**When** the IDE shows the global `Tools` menu or resolves the `Trace Project` action presentation -**Then** the `Trace Project` action is disabled - -Covers: -- `req~disable-trace-project-action-without-open-project~1` - -Needs: dsn - ### Run Trace Project in Background -`scn~run-trace-project-in-background~1` +`scn~run-trace-project-in-background~2` **Given** an IntelliJ project is open and its project directory is available as a local file-system path -**When** a user invokes `Tools | OpenFastTrace | Trace Project` +**When** a user starts an OpenFastTrace trace **Then** the plugin starts an OpenFastTrace trace for that project directory in a background task with visible IDE progress instead of blocking the editor UI Covers: @@ -1195,15 +1161,15 @@ Covers: Needs: dsn -### Show Trace Project in Test Runner UI by Default -`scn~show-trace-project-in-test-runner-ui-by-default~1` +### Show Trace Result in Test Runner UI by Default +`scn~show-trace-result-in-test-runner-ui-by-default~2` **Given** an IntelliJ project is open, its configured trace inputs are valid, and the OFT trace completes -**When** a user invokes `Tools | OpenFastTrace | Trace Project` +**When** a user starts an OpenFastTrace trace **Then** the IDE shows the trace result in the IntelliJ Test Runner UI Covers: -- `req~show-trace-project-in-test-runner-ui-by-default~1` +- `req~show-trace-result-in-test-runner-ui-by-default~2` Needs: dsn @@ -1212,7 +1178,7 @@ Needs: dsn **Given** an IntelliJ project is open **When** a user opens the project settings for the OpenFastTrace plugin -**Then** the user can choose whether `Trace Project` traces the whole project or only selected resources and, for selected-resource tracing, can edit the additional trace paths in a multi-line project-settings field that contains exactly one default entry, `doc/`, until the user changes it +**Then** the user can choose whether the default trace scope uses the whole project or only selected resources and, for selected-resource tracing, can edit the additional trace paths in a multi-line project-settings field that contains exactly one default entry, `doc/`, until the user changes it Covers: - `req~configure-trace-scope-in-project-settings~1` @@ -1222,8 +1188,8 @@ Needs: dsn ### Trace Selected Project Resources `scn~trace-selected-project-resources~1` -**Given** an IntelliJ project is open and the OpenFastTrace project settings are configured for selected-resource tracing -**When** a user invokes `Tools | OpenFastTrace | Trace Project` +**Given** an IntelliJ project is open and the OpenFastTrace project settings or run configuration are configured for selected-resource tracing +**When** a user starts an OpenFastTrace trace **Then** the plugin starts the trace by passing only the resolved selected resources to OpenFastTrace instead of the whole project directory Covers: @@ -1236,7 +1202,7 @@ Needs: dsn `scn~include-intellij-source-directories-in-selected-resource-trace~1` **Given** an IntelliJ project is open, selected-resource tracing is active, and the source-directory option is enabled -**When** a user invokes `Tools | OpenFastTrace | Trace Project` +**When** a user starts an OpenFastTrace trace **Then** the plugin includes the IntelliJ source directories in the effective OpenFastTrace input set Covers: @@ -1248,7 +1214,7 @@ Needs: dsn `scn~include-intellij-test-directories-in-selected-resource-trace~1` **Given** an IntelliJ project is open, selected-resource tracing is active, and the test-directory option is enabled -**When** a user invokes `Tools | OpenFastTrace | Trace Project` +**When** a user starts an OpenFastTrace trace **Then** the plugin includes the IntelliJ test directories in the effective OpenFastTrace input set Covers: @@ -1259,8 +1225,8 @@ Needs: dsn ### Add Project-Relative Paths to Selected-Resource Trace `scn~add-project-relative-paths-to-selected-resource-trace~1` -**Given** an IntelliJ project is open, selected-resource tracing is active, and the OpenFastTrace project settings multi-line field contains additional project-relative file or directory paths -**When** a user invokes `Tools | OpenFastTrace | Trace Project` +**Given** an IntelliJ project is open, selected-resource tracing is active, and the OpenFastTrace project settings or run configuration contains additional project-relative file or directory paths +**When** a user starts an OpenFastTrace trace **Then** the plugin resolves those project-relative files and directories against the opened project and includes them in the effective OpenFastTrace input set Covers: @@ -1280,11 +1246,11 @@ Covers: Needs: dsn -### Reject Trace Project without Valid Project Path -`scn~reject-trace-project-without-valid-project-path~1` +### Reject Trace without Valid Project Path +`scn~reject-trace-without-valid-project-path~1` **Given** an IntelliJ project is open but the plugin cannot resolve a valid local project directory for tracing -**When** a user invokes `Tools | OpenFastTrace | Trace Project` +**When** a user starts an OpenFastTrace trace **Then** the plugin reports that the trace cannot be started because the project path is missing or invalid Covers: @@ -1364,6 +1330,18 @@ Covers: Needs: dsn +### Use Run Configuration Templates +`scn~use-run-configuration-templates~1` + +**Given** an IntelliJ project is open +**When** a user creates a new OpenFastTrace run configuration from a template (e.g., "User Requirements") +**Then** the IDE creates the configuration with the template's pre-configured scope and filters. + +Covers: +- `req~openfasttrace-run-configuration-templates~1` + +Needs: dsn + ### Create and Run OpenFastTrace Run Configuration `scn~create-and-run-openfasttrace-run-configuration~1` From 5b712cf9125ddad5e748cfe2230f347e391e421c Mon Sep 17 00:00:00 2001 From: redcatbaer Date: Sat, 27 Jun 2026 14:17:30 +0200 Subject: [PATCH 2/9] #37: Before fixing trace. --- README.md | 6 +- doc/changes/changelog.md | 1 + doc/changes/changes_0.9.0.md | 19 ++ ...e-global-scan-with-run-config-templates.md | 76 +++++++ doc/design/runtime_view.md | 24 -- gradle.properties | 2 +- .../trace/OftTraceBackgroundRunner.java | 2 +- .../trace/OftTraceInputResolver.java | 2 +- .../trace/OftTraceProjectAction.java | 87 -------- .../trace/OftTraceProjectSettings.java | 2 +- .../runconfig/OftRunConfigurationFactory.java | 28 ++- .../runconfig/OftRunConfigurationType.java | 58 ++++- src/main/resources/META-INF/plugin.xml | 14 -- .../trace/OftTraceProjectActionTest.java | 208 ------------------ .../trace/OftTraceServiceTest.java | 2 +- ...OftRunConfigurationSettingsEditorTest.java | 4 +- .../runconfig/OftRunConfigurationTest.java | 91 +++++++- 17 files changed, 273 insertions(+), 353 deletions(-) create mode 100644 doc/changes/changes_0.9.0.md create mode 100644 doc/changesets/61-replace-global-scan-with-run-config-templates.md delete mode 100644 src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectAction.java delete mode 100644 src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectActionTest.java diff --git a/README.md b/README.md index 7a56fbb..1dfaaf3 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ The plugin currently focuses on: * navigation support (`Go To Declaration`, symbol search, and related navigation paths) * completion for existing specification item IDs while editing `Covers:` entries in supported specification documents and coverage-tag targets in files supported by the OpenFastTrace Tag Importer * bundled OFT live templates for common specification items, including a scenario template -* project-wide or selected-resource OFT tracing from `Tools | OpenFastTrace | Trace Project` or through custom OpenFastTrace run configurations +* project-wide or selected-resource OFT tracing through custom OpenFastTrace run configurations, including pre-configured templates * clickable specification item IDs directly from the trace output window, including generated IDs created from coverage tags * IntelliJ Test Runner UI output for OpenFastTrace traces by default, grouped by source file, specification item, and trace link * quick access to the OpenFastTrace user guide from the IDE help menu @@ -80,11 +80,11 @@ For manual IDE testing, launch a sandbox IDE with the plugin: ## Trace Settings -After the sandbox IDE opens a project, configure trace scope under `Settings | Tools | OpenFastTrace`. By default, `Trace Project` scans the whole opened project. If you switch to selected-resource tracing, the plugin includes IntelliJ source roots, IntelliJ test roots, and one default additional project-relative path entry, `doc/`, until you change it. Additional files or directories are entered one per line. +After the sandbox IDE opens a project, configure trace scope under `Settings | Tools | OpenFastTrace`. The plugin includes IntelliJ source roots, IntelliJ test roots, and one default additional project-relative path entry, `doc/`, until you change it. Additional files or directories are entered one per line. ## Run Configurations -You can create and run a dedicated `OpenFastTrace` run configuration from the IDE's run/debug toolbar. The plugin traces the configured inputs in the background and shows the result in IntelliJ's Test Runner UI by default. The result tree groups source files, specification items, and trace links with pass/fail status and navigation back to source. +You can create and run a dedicated `OpenFastTrace` run configuration from the IDE's run/debug toolbar. The plugin provides pre-configured templates (e.g., "User requirements", "Design and down", "Typical project", "Unfiltered") to quickly set up common scanning scenarios. The plugin traces the configured inputs in the background and shows the result in IntelliJ's Test Runner UI by default. The result tree groups source files, specification items, and trace links with pass/fail status and navigation back to source. Run configurations can select plain text output instead. In that mode, the plugin shows the text report in an IDE output tab with ANSI colors preserved. You can click specification item IDs in the report to jump to their declarations, including source-side items generated from coverage tags. diff --git a/doc/changes/changelog.md b/doc/changes/changelog.md index 683fa74..8a469c7 100644 --- a/doc/changes/changelog.md +++ b/doc/changes/changelog.md @@ -1,5 +1,6 @@ # Changelog +* [0.9.0](changes_0.9.0.md) * [0.8.1](changes_0.8.1.md) * [0.8.0](changes_0.8.0.md) * [0.7.0](changes_0.7.0.md) diff --git a/doc/changes/changes_0.9.0.md b/doc/changes/changes_0.9.0.md new file mode 100644 index 0000000..6e8df4e --- /dev/null +++ b/doc/changes/changes_0.9.0.md @@ -0,0 +1,19 @@ +# OpenFastTrace IntelliJ Plugin 0.9.0, released 2026-06-27 + +Version 0.9.0 introduces specialized run configuration templates and simplifies the plugin UI by removing the redundant global trace menu. + +Users can now quickly set up common OpenFastTrace scanning scenarios using pre-configured templates when creating a new run configuration: +* **User requirements**: Scans `doc/` for core artifact types (`feat, req, scn, bconstr`). +* **Design and down**: Scans `doc/` for all artifact types, including design and build artifacts. +* **Typical project**: Scans `doc/` and all project source directories. +* **Unfiltered**: Scans the entire project without any filters. + +The `Tools | OpenFastTrace | Trace Project` menu has been removed, as the new run configuration templates provide a more flexible and discoverable way to start an OpenFastTrace scan. + +## Bundled OpenFastTrace + +OpenFastTrace 4.5.0 + +## Features + +* #61: Replace global OFT scan with specialized run configuration templates diff --git a/doc/changesets/61-replace-global-scan-with-run-config-templates.md b/doc/changesets/61-replace-global-scan-with-run-config-templates.md new file mode 100644 index 0000000..b819ee9 --- /dev/null +++ b/doc/changesets/61-replace-global-scan-with-run-config-templates.md @@ -0,0 +1,76 @@ +# GH-61 Feature: Replace global OFT scan with specialized run configuration templates + +## Goal + +Remove the redundant global OpenFastTrace scan menu and provide specialized run configuration templates to allow users to quickly set up common scanning scenarios. + +## Scope + +In scope: + +* Remove the 'Trace Project' action and its associated 'OpenFastTrace' menu group from the IntelliJ 'Tools' menu. +* Introduce the following pre-configured run configuration templates: + - **User requirements**: Scans `doc/`, excludes source directories, filters for artifact types: `feat, req, scn, bconstr`. + - **Design and down**: Scans `doc/`, excludes source directories, filters for artifact types: `feat, req, scn, bconstr, arch, dsn, constr, bld`. + - **Typical project**: Scans `doc/` and all project source directories, with no artifact type filtering. + - **Unfiltered**: Scans the entire project (`.`) with no filters. +* Leverage the IntelliJ `ConfigurationFactory` mechanism to provide these templates as sub-items in the "Add New Configuration" menu. + +Out of scope: + +* Adding new configuration options beyond what is currently supported. +* Changing the trace execution engine or result presentation. + +## Design References + +* [System Requirements](../system_requirements.md) +* [Quality Requirements](../design/quality_requirements.md) +* [Runtime View](../design/runtime_view.md) + +## Strategy + +We will update `OftRunConfigurationType` to register multiple `ConfigurationFactory` instances. Each factory will be initialized with a specific `OftTraceSettingsSnapshot` to provide the template behavior. The `OftRunConfigurationFactory` will be modified to accept these initial settings. + +The global action `OftTraceProjectAction` and its registration in `plugin.xml` will be removed. + +## Task List + +- [x] Create and checkout a new Git branch `feature/61-run-config-templates` + +### Requirements And Design + +- [x] Update `doc/system_requirements.md` to remove the global trace action and document run configuration templates. +- [x] Stop and ask user for a review of the system requirements +- [x] Update `doc/design/runtime_view.md` to reflect the multi-factory approach for run configurations. +- [x] Stop and ask user for a review of the design + +### Implementation + +- [ ] Implement the logic to ignore trailing numbers in `impl`, `utest`, and `itest` IDs during tracing. +- [x] Modify `OftRunConfigurationFactory` to support template-based initialization. +- [x] Update `OftRunConfigurationType` to register the four requested templates. +- [x] Remove `OftTraceProjectAction.java` and any classes only used by it. +- [x] Remove `Oft.ToolsMenu` and related actions from `src/main/resources/META-INF/plugin.xml`. + +### Verification + +- [ ] Add a verification test for ignoring trailing numbers in implementation and test artifact types. +- [x] Update `OftRunConfigurationTest` to verify template-based initialization. +- [ ] Run `check` task to ensure all tests pass and requirements trace is clean. +- [ ] Keep the OpenFastTrace trace clean +- [ ] Keep required build and plugin verification tasks green + +### Update user documentation + +- [x] Update `README.md` to reflect the removal of the Tools menu and the addition of run configuration templates. + +## Version and Changelog Update + +- [ ] Check if the current version mentioned in the build scripts and code parameters is the same as the latest GitHub release. +- [x] Raise the version to 0.9.0 (this is a feature release) +- [x] Write the changelog entry for 0.9.0 in `doc/changes/changes_0.9.0.md` +- [x] Update `doc/changes/changelog.md` to include 0.9.0 +- [x] Update version in `build.gradle.kts` +- [x] Write the bundled OpenFastTrace version into the fixed changelog location for 0.9.0 +- [x] Update release date to today +- [ ] Ensure that issue list contains the GitHub issue number and title diff --git a/doc/design/runtime_view.md b/doc/design/runtime_view.md index 5d5fbfa..ccf98bc 100644 --- a/doc/design/runtime_view.md +++ b/doc/design/runtime_view.md @@ -376,18 +376,6 @@ Covers: Needs: impl, itest -### Configure Trace Scope in Project Settings -`dsn~configure-trace-scope-in-project-settings~2` - -**Given** an IntelliJ project is open -**When** a user opens the OpenFastTrace project settings -**Then** the trace-configuration component loads the persisted trace-scope mode and lets the user switch between whole-project tracing and selected-resource tracing for that project. - -Covers: -- `scn~configure-trace-scope-in-project-settings~1` - -Needs: impl, itest - ### Trace Selected Project Resources `dsn~trace-selected-project-resources~2` @@ -448,18 +436,6 @@ Covers: Needs: impl, itest -### Reject Trace without Valid Project Path -`dsn~reject-trace-without-valid-project-path~1` - -**Given** an IntelliJ project is open but its base directory is missing, invalid, or not usable as a local OpenFastTrace input path -**When** a user starts an OpenFastTrace trace -**Then** the trace flow stops before starting the background trace run and reports the invalid project-path or configured-input condition through the IDE-visible trace flow. - -Covers: -- `scn~reject-trace-without-valid-project-path~1` - -Needs: impl, itest - ### Use Run Configuration Templates `dsn~use-run-configuration-templates~1` diff --git a/gradle.properties b/gradle.properties index eac6a12..8eef264 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -version=0.8.1 +version=0.9.0 org.gradle.configuration-cache=true org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8 diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceBackgroundRunner.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceBackgroundRunner.java index cfca8f8..b6c9d15 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceBackgroundRunner.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceBackgroundRunner.java @@ -26,7 +26,7 @@ public OftTraceBackgroundRunner( this.processHandler = processHandler; } - // [impl->dsn~run-trace-project-in-background~1] + // [impl->dsn~run-trace-project-in-background~2] @Override public void run(final Project project, final OftTraceInputs inputs, final String contentTitle) { ProgressManager.getInstance().run(new TraceTask(project, inputs, contentTitle)); diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolver.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolver.java index 52304c5..92ef97e 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolver.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolver.java @@ -110,7 +110,7 @@ static OftTraceInputResolution resolveProjectRoot(final String basePath, final O )); } - // [impl->dsn~trace-selected-project-resources~1] + // [impl->dsn~trace-selected-project-resources~2] // [impl->dsn~include-intellij-source-directories-in-selected-resource-trace~1] // [impl->dsn~include-intellij-test-directories-in-selected-resource-trace~1] // [impl->dsn~add-project-relative-paths-to-selected-resource-trace~1] diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectAction.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectAction.java deleted file mode 100644 index e74f906..0000000 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectAction.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.itsallcode.openfasttrace.intellijplugin.trace; - -import com.intellij.execution.process.NopProcessHandler; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.project.DumbAwareAction; -import com.intellij.openapi.project.Project; - -import java.util.function.Function; - -// [impl->dsn~trace-action-integration~2] -// [impl->dsn~show-trace-project-action-in-tools-menu~1] -// [impl->dsn~disable-trace-project-action-without-open-project~1] -// [impl->dsn~show-trace-project-in-test-runner-ui-by-default~1] -public final class OftTraceProjectAction extends DumbAwareAction { - public static final String ACTION_ID = "Oft.TraceProject.ToolsMenu"; - public static final String TOOLS_GROUP_ID = "Oft.ToolsMenu"; - - private final Function projectInputResolver; - private final OftTraceRunner traceRunner; - private final OftTraceOutputPresenter outputPresenter; - - public OftTraceProjectAction() { - this(defaultDependencies()); - } - - private OftTraceProjectAction(final DefaultDependencies dependencies) { - this( - OftTraceInputResolver::resolve, - dependencies.traceRunner(), - dependencies.outputPresenter() - ); - } - - OftTraceProjectAction( - final Function projectInputResolver, - final OftTraceRunner traceRunner, - final OftTraceOutputPresenter outputPresenter - ) { - this.projectInputResolver = projectInputResolver; - this.traceRunner = traceRunner; - this.outputPresenter = outputPresenter; - } - - @Override - public void actionPerformed(final AnActionEvent event) { - final Project project = event.getProject(); - if (project == null) { - return; - } - final String contentTitle = createContentTitle(project); - final OftTraceInputResolution resolution = projectInputResolver.apply(project); - if (!resolution.isValid()) { - // [impl->dsn~reject-trace-project-without-valid-project-path~2] - outputPresenter.show(project, contentTitle, OftTraceResult.invalidInput(resolution.errorMessage())); - return; - } - traceRunner.run(project, resolution.inputs(), contentTitle); - } - - @Override - public void update(final AnActionEvent event) { - event.getPresentation().setEnabled(event.getProject() != null); - } - - static String createContentTitle(final Project project) { - return "OpenFastTrace Trace: " + project.getName(); - } - - static OftTraceOutputPresenter createDefaultOutputPresenter() { - return new OftTraceTestRunnerRunContentOutputPresenter(); - } - - private static DefaultDependencies defaultDependencies() { - final OftTraceOutputPresenter presenter = createDefaultOutputPresenter(); - return new DefaultDependencies( - new OftTraceBackgroundRunner( - new OftTraceService(), - presenter, - new NopProcessHandler() - ), - presenter - ); - } - - private record DefaultDependencies(OftTraceRunner traceRunner, OftTraceOutputPresenter outputPresenter) { - } -} diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectSettings.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectSettings.java index ceb669b..fbd1388 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectSettings.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectSettings.java @@ -11,7 +11,7 @@ name = "org.itsallcode.openfasttrace.intellijplugin.trace.OftTraceProjectSettings", storages = @Storage("openfasttrace.xml") ) -// [impl->dsn~trace-configuration-integration~1] +// [impl->dsn~trace-configuration-integration~2] final class OftTraceProjectSettings implements PersistentStateComponent { private State state = new State(); diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationFactory.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationFactory.java index fa72d70..bf21b28 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationFactory.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationFactory.java @@ -4,20 +4,44 @@ import com.intellij.execution.configurations.ConfigurationType; import com.intellij.execution.configurations.RunConfiguration; import com.intellij.openapi.project.Project; +import org.itsallcode.openfasttrace.intellijplugin.trace.OftTraceSettingsSnapshot; import org.jetbrains.annotations.NotNull; +import java.util.function.Consumer; + public final class OftRunConfigurationFactory extends ConfigurationFactory { + private final String factoryName; + private final Consumer initializer; + public OftRunConfigurationFactory(final ConfigurationType type) { + this(type, "General Scan", config -> { + }); + } + + public OftRunConfigurationFactory( + final ConfigurationType type, + final String factoryName, + final Consumer initializer + ) { super(type); + this.factoryName = factoryName; + this.initializer = initializer; } @Override public @NotNull RunConfiguration createTemplateConfiguration(@NotNull final Project project) { - return new OftRunConfiguration(project, this, "OpenFastTrace"); + final OftRunConfiguration configuration = new OftRunConfiguration(project, this, "OpenFastTrace"); + this.initializer.accept(configuration); + return configuration; + } + + @Override + public @NotNull String getName() { + return this.factoryName; } @Override public @NotNull String getId() { - return OftRunConfigurationType.ID; + return OftRunConfigurationType.ID + "." + this.factoryName.replace(" ", ""); } } diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationType.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationType.java index 40bc1d1..4ac35ff 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationType.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationType.java @@ -3,14 +3,68 @@ import com.intellij.execution.configurations.ConfigurationTypeBase; import com.intellij.openapi.util.NotNullLazyValue; import org.itsallcode.openfasttrace.intellijplugin.OftIcons; +import org.itsallcode.openfasttrace.intellijplugin.trace.OftTraceResultView; +import org.itsallcode.openfasttrace.intellijplugin.trace.OftTraceScopeMode; +import org.itsallcode.openfasttrace.intellijplugin.trace.OftTraceSettingsSnapshot; -// [impl->dsn~openfasttrace-run-configuration~1] +// [impl->dsn~openfasttrace-run-configuration~2] public final class OftRunConfigurationType extends ConfigurationTypeBase { public static final String ID = "OpenFastTraceRunConfiguration"; public OftRunConfigurationType() { super(ID, "OpenFastTrace", "OpenFastTrace run configuration", NotNullLazyValue.createValue(() -> OftIcons.OPEN_FAST_TRACE)); - addFactory(new OftRunConfigurationFactory(this)); + + addFactory(new OftRunConfigurationFactory(this, "User requirements", config -> { + final OftTraceSettingsSnapshot snapshot = new OftTraceSettingsSnapshot( + OftTraceScopeMode.SELECTED_RESOURCES, + false, + false, + "doc/", + "feat, req, scn, bconstr", + "", + OftTraceResultView.TEST_RUNNER + ); + config.updateFrom(snapshot); + })); + + addFactory(new OftRunConfigurationFactory(this, "Design and down", config -> { + final OftTraceSettingsSnapshot snapshot = new OftTraceSettingsSnapshot( + OftTraceScopeMode.SELECTED_RESOURCES, + false, + false, + "doc/", + "feat, req, scn, bconstr, arch, dsn, constr, bld", + "", + OftTraceResultView.TEST_RUNNER + ); + config.updateFrom(snapshot); + })); + + addFactory(new OftRunConfigurationFactory(this, "Typical project", config -> { + final OftTraceSettingsSnapshot snapshot = new OftTraceSettingsSnapshot( + OftTraceScopeMode.SELECTED_RESOURCES, + true, + true, + "doc/", + "", + "", + OftTraceResultView.TEST_RUNNER + ); + config.updateFrom(snapshot); + })); + + addFactory(new OftRunConfigurationFactory(this, "Unfiltered", config -> { + final OftTraceSettingsSnapshot snapshot = new OftTraceSettingsSnapshot( + OftTraceScopeMode.WHOLE_PROJECT, + false, + false, + ".", + "", + "", + OftTraceResultView.TEST_RUNNER + ); + config.updateFrom(snapshot); + })); } } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index eb52404..2e40110 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -139,20 +139,6 @@ - - - - - - dsn~trace-action-integration~2] -public class OftTraceProjectActionTest extends AbstractOftPlatformTestCase { - // [itest->dsn~show-trace-project-action-in-tools-menu~1] - public void testGivenPluginIsLoadedWhenToolsMenuActionIsQueriedThenTheTraceActionAndGroupAreRegistered() { - final AnAction group = ActionManager.getInstance().getAction(OftTraceProjectAction.TOOLS_GROUP_ID); - final AnAction action = ActionManager.getInstance().getAction(OftTraceProjectAction.ACTION_ID); - - Assertions.assertAll( - () -> assertThat(group, notNullValue()), - () -> assertThat(action, notNullValue()), - () -> assertThat(group, instanceOf(com.intellij.openapi.actionSystem.DefaultActionGroup.class)), - () -> assertThat(((com.intellij.openapi.actionSystem.DefaultActionGroup) group).isPopup(), is(true)), - () -> assertThat( - Arrays.asList( - ((com.intellij.openapi.actionSystem.DefaultActionGroup) group) - .getChildren((AnActionEvent) null) - ), - contains(action) - ) - ); - } - - public void testGivenTraceActionShortcutWhenQueryingKeymapThenItIsBoundOnlyToTheTraceAction() { - final Keymap keymap = KeymapManager.getInstance().getActiveKeymap(); - final KeyStroke keyStroke = KeyStroke.getKeyStroke("ctrl alt shift O"); - final String[] actionIds = keymap.getActionIds(keyStroke); - - Assertions.assertAll( - () -> assertThat(keymap.getShortcuts(OftTraceProjectAction.ACTION_ID).length, is(1)), - () -> assertThat(actionIds, hasItemInArray(OftTraceProjectAction.ACTION_ID)), - () -> assertThat(actionIds.length, is(1)) - ); - } - - public void testGivenProjectWhenActionUpdatesThenPresentationIsEnabled() { - final OftTraceProjectAction action = new OftTraceProjectAction(); - final Presentation presentation = new Presentation(); - - action.update(createEvent(getProject(), presentation)); - - assertThat(presentation.isEnabled(), is(true)); - } - - // [itest->dsn~show-trace-project-in-test-runner-ui-by-default~1] - public void testGivenDefaultActionWhenCreatingDefaultPresenterThenItUsesTestRunnerRunContentPresenter() { - assertThat( - OftTraceProjectAction.createDefaultOutputPresenter(), - instanceOf(OftTraceTestRunnerRunContentOutputPresenter.class) - ); - } - - // [itest->dsn~disable-trace-project-action-without-open-project~1] - public void testGivenNoProjectWhenActionUpdatesThenPresentationIsDisabled() { - final OftTraceProjectAction action = new OftTraceProjectAction(); - final Presentation presentation = new Presentation(); - - action.update(createEvent(null, presentation)); - - assertThat(presentation.isEnabled(), is(false)); - } - - // [itest->dsn~run-trace-project-in-background~1] - public void testGivenProjectWhenActionPerformsThenItStartsTheTraceRunnerWithTheProjectBasePath() throws IOException { - final AtomicReference runnerCall = new AtomicReference<>(); - final AtomicReference presenterCall = new AtomicReference<>(); - final Path projectRoot = createManagedTestArtifactDirectory("trace-project-action-input"); - final Project project = projectProxy(projectRoot.toString(), "valid-project"); - final OftTraceProjectAction action = new OftTraceProjectAction( - testProject -> OftTraceInputResolution.valid(OftTraceInputs.wholeProject(projectRoot, List.of(), List.of())), - (runnerProject, inputs, contentTitle) -> - runnerCall.set(new RunnerCall(runnerProject, inputs, contentTitle)), - (presentedProject, contentTitle, result) -> - presenterCall.set(new PresenterCall(presentedProject, contentTitle, result)) - ); - - ApplicationManager.getApplication().invokeAndWait(() -> action.actionPerformed(createEvent(project))); - - Assertions.assertAll( - () -> assertThat(runnerCall.get(), notNullValue()), - () -> assertThat(runnerCall.get().project(), sameInstance(project)), - () -> assertThat(runnerCall.get().inputs().inputPaths(), contains(projectRoot)), - () -> assertThat( - runnerCall.get().contentTitle(), - is(OftTraceProjectAction.createContentTitle(project)) - ), - () -> assertThat(presenterCall.get(), is(nullValue())) - ); - } - - // [itest->dsn~reject-trace-project-without-valid-project-path~2] - public void testGivenInvalidProjectBasePathWhenActionPerformsThenItReportsTheStartupFailureThroughThePresenter() { - final AtomicReference runnerCall = new AtomicReference<>(); - final AtomicReference presenterCall = new AtomicReference<>(); - final Project project = projectProxy("/definitely/missing/openfasttrace/project", "invalid-project"); - final OftTraceProjectAction action = new OftTraceProjectAction( - testProject -> OftTraceInputResolution.invalid("The current project base path does not exist"), - (runProject, inputs, contentTitle) -> runnerCall.set(new RunnerCall(runProject, inputs, contentTitle)), - (presentedProject, contentTitle, result) -> - presenterCall.set(new PresenterCall(presentedProject, contentTitle, result)) - ); - - ApplicationManager.getApplication().invokeAndWait(() -> action.actionPerformed(createEvent(project))); - - Assertions.assertAll( - () -> assertThat(runnerCall.get(), is(nullValue())), - () -> assertThat(presenterCall.get(), notNullValue()), - () -> assertThat(presenterCall.get().project(), sameInstance(project)), - () -> assertThat(presenterCall.get().contentTitle(), is("OpenFastTrace Trace: invalid-project")), - () -> assertThat(presenterCall.get().result().requiresAttention(), is(true)), - () -> assertThat( - presenterCall.get().result().output(), - Matchers.containsString("does not exist") - ) - ); - } - - public void testGivenNoProjectWhenActionPerformsThenItDoesNothing() { - final AtomicReference runnerCall = new AtomicReference<>(); - final AtomicReference presenterCall = new AtomicReference<>(); - final OftTraceProjectAction action = new OftTraceProjectAction( - testProject -> OftTraceInputResolution.invalid("unused"), - (project, inputs, contentTitle) -> runnerCall.set(new RunnerCall(project, inputs, contentTitle)), - (project, contentTitle, result) -> presenterCall.set(new PresenterCall(project, contentTitle, result)) - ); - - ApplicationManager.getApplication().invokeAndWait(() -> action.actionPerformed(createEvent(null))); - - Assertions.assertAll( - () -> assertThat(runnerCall.get(), is(nullValue())), - () -> assertThat(presenterCall.get(), is(nullValue())) - ); - } - - private AnActionEvent createEvent(final Project project) { - return createEvent(project, new Presentation()); - } - - private AnActionEvent createEvent(final Project project, final Presentation presentation) { - final SimpleDataContext.Builder builder = SimpleDataContext.builder(); - if (project != null) { - builder.add(CommonDataKeys.PROJECT, project); - } - return AnActionEvent.createEvent( - builder.build(), - presentation, - ActionPlaces.UNKNOWN, - ActionUiKind.NONE, - null - ); - } - - private Project projectProxy(final String basePath, final String name) { - return (Project) Proxy.newProxyInstance( - Project.class.getClassLoader(), - new Class[]{Project.class}, - (proxy, method, args) -> switch (method.getName()) { - case "getBasePath" -> basePath; - case "getName" -> name; - case "isDisposed" -> false; - case "equals" -> proxy == args[0]; - case "hashCode" -> System.identityHashCode(proxy); - case "toString" -> "Project[" + name + "]"; - default -> throw new UnsupportedOperationException(method.getName()); - } - ); - } - - private record RunnerCall(Project project, OftTraceInputs inputs, String contentTitle) { - } - - private record PresenterCall(Project project, String contentTitle, OftTraceResult result) { - } -} diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceServiceTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceServiceTest.java index 9f2696e..1c34744 100644 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceServiceTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceServiceTest.java @@ -261,7 +261,7 @@ private String stripAnsi(final String output) { return ANSI_ESCAPE_SEQUENCE.matcher(output).replaceAll(""); } - // [itest->dsn~trace-selected-project-resources~1] + // [itest->dsn~trace-selected-project-resources~2] // [itest->dsn~show-resolved-trace-inputs-in-trace-output-window~1] @Test void testGivenSelectedResourceInputsWhenTracingThenItListsConfiguredInputsAndIgnoresOutOfScopeArtifacts( diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationSettingsEditorTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationSettingsEditorTest.java index 57c9631..684eb32 100644 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationSettingsEditorTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationSettingsEditorTest.java @@ -27,7 +27,7 @@ public void testGivenEditorWhenCreatingEditorThenItReturnsNonNullComponent() { } // [itest->dsn~select-test-runner-trace-result-view~1] - // [itest->dsn~trace-configuration-integration~1] + // [itest->dsn~trace-configuration-integration~2] public void testGivenEditorWhenResettingFromConfigurationThenItUpdatesUI() { editor.createEditor(); // Initialize component final OftRunConfiguration configuration = createConfiguration("Test"); @@ -58,7 +58,7 @@ public void testGivenEditorWhenResettingFromConfigurationThenItUpdatesUI() { } // [itest->dsn~select-test-runner-trace-result-view~1] - // [itest->dsn~trace-configuration-integration~1] + // [itest->dsn~trace-configuration-integration~2] public void testGivenEditorWhenApplyingToConfigurationThenItUpdatesConfiguration() { editor.createEditor(); // Initialize component final OftTraceSettingsSnapshot snapshot = new OftTraceSettingsSnapshot( diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java index 3004afe..0ab205f 100644 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java @@ -1,5 +1,6 @@ package org.itsallcode.openfasttrace.intellijplugin.trace.runconfig; +import com.intellij.execution.configurations.ConfigurationFactory; import com.intellij.icons.AllIcons; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; @@ -11,15 +12,18 @@ import org.jdom.Element; import org.junit.jupiter.api.Assertions; +import java.util.Arrays; + import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.sameInstance; -// [itest->dsn~openfasttrace-run-configuration~1] +// [itest->dsn~openfasttrace-run-configuration~2] public class OftRunConfigurationTest extends AbstractOftPlatformTestCase { // [itest->dsn~test-runner-as-default-run-configuration-result-view~1] - // [itest->dsn~trace-configuration-integration~1] + // [itest->dsn~trace-configuration-integration~2] public void testGivenNewRunConfigurationWhenReadingSnapshotThenItDefaultsToTestRunner() { final OftRunConfiguration configuration = createConfiguration("Test"); @@ -27,7 +31,7 @@ public void testGivenNewRunConfigurationWhenReadingSnapshotThenItDefaultsToTestR } // [itest->dsn~select-test-runner-trace-result-view~1] - // [itest->dsn~trace-configuration-integration~1] + // [itest->dsn~trace-configuration-integration~2] public void testGivenRunConfigurationWhenUpdatingFromSnapshotThenItStoresTheSettings() { final OftRunConfiguration configuration = createConfiguration("Test"); final OftTraceSettingsSnapshot snapshot = new OftTraceSettingsSnapshot( @@ -55,7 +59,7 @@ public void testGivenRunConfigurationWhenUpdatingFromSnapshotThenItStoresTheSett } // [itest->dsn~select-test-runner-trace-result-view~1] - // [itest->dsn~trace-configuration-integration~1] + // [itest->dsn~trace-configuration-integration~2] public void testGivenRunConfigurationWithSettingsWhenWritingAndReadingExternalThenItPreservesSettings() throws WriteExternalException, InvalidDataException { final OftRunConfiguration configuration = createConfiguration("Test"); @@ -89,7 +93,7 @@ public void testGivenRunConfigurationWithSettingsWhenWritingAndReadingExternalTh } // [itest->dsn~test-runner-as-default-run-configuration-result-view~1] - // [itest->dsn~trace-configuration-integration~1] + // [itest->dsn~trace-configuration-integration~2] public void testGivenRunConfigurationWithNoStoredResultViewWhenReadingExternalThenItDefaultsToTestRunner() throws InvalidDataException { final OftRunConfiguration configuration = createConfiguration("Test"); @@ -100,7 +104,7 @@ public void testGivenRunConfigurationWithNoStoredResultViewWhenReadingExternalTh } // [itest->dsn~test-runner-as-default-run-configuration-result-view~1] - // [itest->dsn~trace-configuration-integration~1] + // [itest->dsn~trace-configuration-integration~2] public void testGivenRunConfigurationWithInvalidStoredResultViewWhenReadingExternalThenItDefaultsToTestRunner() throws InvalidDataException { final Element element = new Element("configuration"); @@ -124,9 +128,84 @@ public void testGivenRunConfigurationTypeWhenReadingIconThenItUsesTheOpenFastTra ); } + public void testGivenRunConfigurationTypeWhenCheckingFactoriesThenItContainsAllTemplates() { + final OftRunConfigurationType type = new OftRunConfigurationType(); + final String[] factoryNames = Arrays.stream(type.getConfigurationFactories()) + .map(ConfigurationFactory::getName) + .toArray(String[]::new); + + assertThat(Arrays.asList(factoryNames), containsInAnyOrder( + "User requirements", + "Design and down", + "Typical project", + "Unfiltered" + )); + } + + public void testGivenUserRequirementsTemplateWhenCreatingConfigurationThenItHasCorrectSettings() { + final OftRunConfiguration configuration = createConfigurationFromTemplate("User requirements"); + final OftTraceSettingsSnapshot snapshot = configuration.snapshot(); + + Assertions.assertAll( + () -> assertThat(snapshot.scopeMode(), is(OftTraceScopeMode.SELECTED_RESOURCES)), + () -> assertThat(snapshot.includeSourceRoots(), is(false)), + () -> assertThat(snapshot.includeTestRoots(), is(false)), + () -> assertThat(snapshot.additionalPathsText(), is("doc/")), + () -> assertThat(snapshot.artifactTypesText(), is("feat, req, scn, bconstr")) + ); + } + + public void testGivenDesignAndDownTemplateWhenCreatingConfigurationThenItHasCorrectSettings() { + final OftRunConfiguration configuration = createConfigurationFromTemplate("Design and down"); + final OftTraceSettingsSnapshot snapshot = configuration.snapshot(); + + Assertions.assertAll( + () -> assertThat(snapshot.scopeMode(), is(OftTraceScopeMode.SELECTED_RESOURCES)), + () -> assertThat(snapshot.includeSourceRoots(), is(false)), + () -> assertThat(snapshot.includeTestRoots(), is(false)), + () -> assertThat(snapshot.additionalPathsText(), is("doc/")), + () -> assertThat(snapshot.artifactTypesText(), is("feat, req, scn, bconstr, arch, dsn, constr, bld")) + ); + } + + public void testGivenTypicalProjectTemplateWhenCreatingConfigurationThenItHasCorrectSettings() { + final OftRunConfiguration configuration = createConfigurationFromTemplate("Typical project"); + final OftTraceSettingsSnapshot snapshot = configuration.snapshot(); + + Assertions.assertAll( + () -> assertThat(snapshot.scopeMode(), is(OftTraceScopeMode.SELECTED_RESOURCES)), + () -> assertThat(snapshot.includeSourceRoots(), is(true)), + () -> assertThat(snapshot.includeTestRoots(), is(true)), + () -> assertThat(snapshot.additionalPathsText(), is("doc/")), + () -> assertThat(snapshot.artifactTypesText(), is("")) + ); + } + + public void testGivenUnfilteredTemplateWhenCreatingConfigurationThenItHasCorrectSettings() { + final OftRunConfiguration configuration = createConfigurationFromTemplate("Unfiltered"); + final OftTraceSettingsSnapshot snapshot = configuration.snapshot(); + + Assertions.assertAll( + () -> assertThat(snapshot.scopeMode(), is(OftTraceScopeMode.WHOLE_PROJECT)), + () -> assertThat(snapshot.includeSourceRoots(), is(false)), + () -> assertThat(snapshot.includeTestRoots(), is(false)), + () -> assertThat(snapshot.additionalPathsText(), is(".")), + () -> assertThat(snapshot.artifactTypesText(), is("")) + ); + } + private OftRunConfiguration createConfiguration(final String name) { final OftRunConfigurationType type = new OftRunConfigurationType(); final OftRunConfigurationFactory factory = (OftRunConfigurationFactory) type.getConfigurationFactories()[0]; return new OftRunConfiguration(getProject(), factory, name); } + + private OftRunConfiguration createConfigurationFromTemplate(final String templateName) { + final OftRunConfigurationType type = new OftRunConfigurationType(); + final OftRunConfigurationFactory factory = (OftRunConfigurationFactory) Arrays.stream(type.getConfigurationFactories()) + .filter(f -> f.getName().equals(templateName)) + .findFirst() + .orElseThrow(); + return (OftRunConfiguration) factory.createTemplateConfiguration(getProject()); + } } From c39de67c47504c91a449af52fe5add078920a4be Mon Sep 17 00:00:00 2001 From: redcatbaer Date: Sat, 27 Jun 2026 14:19:59 +0200 Subject: [PATCH 3/9] #37: Added missing design requirement. --- doc/design/building_block_view.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/design/building_block_view.md b/doc/design/building_block_view.md index d61f529..a1d7702 100644 --- a/doc/design/building_block_view.md +++ b/doc/design/building_block_view.md @@ -251,6 +251,16 @@ Covers: Needs: impl, itest +### Configure Trace Scope in Project Settings +`dsn~configure-trace-scope-in-project-settings~1` + +The plugin provides a project-level settings page for OpenFastTrace that allows users to configure the default trace scope for the project. Users can choose between whole-project tracing and selected-resource tracing. For selected-resource tracing, the settings provide a multi-line text field for additional project-relative paths, initialized with a default `doc/` entry. + +Covers: +- `scn~configure-trace-scope-in-project-settings~1` + +Needs: impl, itest + ### Trace Action Integration `dsn~trace-action-integration~3` From 788b496554bfa3e4b92e62beb7c3d10ee3b96d57 Mon Sep 17 00:00:00 2001 From: redcatbaer Date: Sat, 27 Jun 2026 21:35:43 +0200 Subject: [PATCH 4/9] #37: Run configuration templates. --- README.md | 2 +- doc/changes/changes_0.9.0.md | 2 +- .../61-replace-global-scan-with-run-config-templates.md | 2 +- doc/system_requirements.md | 2 +- .../intellijplugin/trace/OftTraceBackgroundRunner.java | 1 + .../OftTraceTestRunnerRunContentOutputPresenter.java | 2 +- .../trace/runconfig/OftRunConfiguration.java | 5 +++++ .../trace/runconfig/OftRunConfigurationFactory.java | 2 +- .../trace/runconfig/OftRunConfigurationType.java | 2 +- .../trace/runconfig/OftRunProfileState.java | 1 + .../trace/OftTraceBackgroundRunnerTest.java | 2 ++ .../OftTraceTestRunnerRunContentOutputPresenterTest.java | 2 +- .../trace/runconfig/OftRunConfigurationTest.java | 9 ++++++--- .../trace/runconfig/OftRunProfileStateTest.java | 1 + 14 files changed, 24 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 1dfaaf3..3d7ef9f 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ After the sandbox IDE opens a project, configure trace scope under `Settings | T ## Run Configurations -You can create and run a dedicated `OpenFastTrace` run configuration from the IDE's run/debug toolbar. The plugin provides pre-configured templates (e.g., "User requirements", "Design and down", "Typical project", "Unfiltered") to quickly set up common scanning scenarios. The plugin traces the configured inputs in the background and shows the result in IntelliJ's Test Runner UI by default. The result tree groups source files, specification items, and trace links with pass/fail status and navigation back to source. +You can create and run a dedicated `OpenFastTrace` run configuration from the IDE's run/debug toolbar. The plugin provides pre-configured templates (e.g., "User requirements", "Design and above", "Typical project", "Unfiltered") to quickly set up common scanning scenarios. The plugin traces the configured inputs in the background and shows the result in IntelliJ's Test Runner UI by default. The result tree groups source files, specification items, and trace links with pass/fail status and navigation back to source. Run configurations can select plain text output instead. In that mode, the plugin shows the text report in an IDE output tab with ANSI colors preserved. You can click specification item IDs in the report to jump to their declarations, including source-side items generated from coverage tags. diff --git a/doc/changes/changes_0.9.0.md b/doc/changes/changes_0.9.0.md index 6e8df4e..fbc4f51 100644 --- a/doc/changes/changes_0.9.0.md +++ b/doc/changes/changes_0.9.0.md @@ -4,7 +4,7 @@ Version 0.9.0 introduces specialized run configuration templates and simplifies Users can now quickly set up common OpenFastTrace scanning scenarios using pre-configured templates when creating a new run configuration: * **User requirements**: Scans `doc/` for core artifact types (`feat, req, scn, bconstr`). -* **Design and down**: Scans `doc/` for all artifact types, including design and build artifacts. +* **Design and above**: Scans `doc/` for all artifact types, including design and build artifacts. * **Typical project**: Scans `doc/` and all project source directories. * **Unfiltered**: Scans the entire project without any filters. diff --git a/doc/changesets/61-replace-global-scan-with-run-config-templates.md b/doc/changesets/61-replace-global-scan-with-run-config-templates.md index b819ee9..c95282b 100644 --- a/doc/changesets/61-replace-global-scan-with-run-config-templates.md +++ b/doc/changesets/61-replace-global-scan-with-run-config-templates.md @@ -11,7 +11,7 @@ In scope: * Remove the 'Trace Project' action and its associated 'OpenFastTrace' menu group from the IntelliJ 'Tools' menu. * Introduce the following pre-configured run configuration templates: - **User requirements**: Scans `doc/`, excludes source directories, filters for artifact types: `feat, req, scn, bconstr`. - - **Design and down**: Scans `doc/`, excludes source directories, filters for artifact types: `feat, req, scn, bconstr, arch, dsn, constr, bld`. + - **Design and above**: Scans `doc/`, excludes source directories, filters for artifact types: `feat, req, scn, bconstr, arch, dsn, constr, bld`. - **Typical project**: Scans `doc/` and all project source directories, with no artifact type filtering. - **Unfiltered**: Scans the entire project (`.`) with no filters. * Leverage the IntelliJ `ConfigurationFactory` mechanism to provide these templates as sub-items in the "Add New Configuration" menu. diff --git a/doc/system_requirements.md b/doc/system_requirements.md index 492e33e..05f318d 100644 --- a/doc/system_requirements.md +++ b/doc/system_requirements.md @@ -451,7 +451,7 @@ Needs: scn The plugin provides pre-configured templates when creating new OpenFastTrace run configurations. These templates allow users to quickly set up common scanning scenarios. The following templates are available: - **User requirements**: Scans `doc/`, excludes source directories, filters for artifact types: `feat, req, scn, bconstr`. -- **Design and down**: Scans `doc/`, excludes source directories, filters for artifact types: `feat, req, scn, bconstr, arch, dsn, constr`. +- **Design and above**: Scans `doc/`, excludes source directories, filters for artifact types: `feat, req, scn, bconstr, arch, dsn, constr`. - **Typical project**: Scans `doc/` and all project source directories, with no artifact type filtering. - **Unfiltered**: Scans the entire project (`.`) with no filters. diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceBackgroundRunner.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceBackgroundRunner.java index b6c9d15..d419f56 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceBackgroundRunner.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceBackgroundRunner.java @@ -27,6 +27,7 @@ public OftTraceBackgroundRunner( } // [impl->dsn~run-trace-project-in-background~2] + // [impl->dsn~trace-action-integration~3] @Override public void run(final Project project, final OftTraceInputs inputs, final String contentTitle) { ProgressManager.getInstance().run(new TraceTask(project, inputs, contentTitle)); diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceTestRunnerRunContentOutputPresenter.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceTestRunnerRunContentOutputPresenter.java index 13b4102..c3af6b9 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceTestRunnerRunContentOutputPresenter.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceTestRunnerRunContentOutputPresenter.java @@ -38,7 +38,7 @@ public OftTraceTestRunnerRunContentOutputPresenter() { this.runContentShower = runContentShower; } - // [impl->dsn~show-trace-project-in-test-runner-ui-by-default~1] + // [impl->dsn~show-trace-result-in-test-runner-ui-by-default~2] @Override public void show(final Project project, final String contentTitle, final OftTraceResult result) { final AtomicReference consoleRef = new AtomicReference<>(); diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfiguration.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfiguration.java index e61b57f..846dddc 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfiguration.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfiguration.java @@ -62,6 +62,11 @@ public void updateFrom(final OftTraceSettingsSnapshot snapshot) { state.setResultView(snapshot.resultView().name()); } + @Override + public String suggestedName() { + return getFactory().getName(); + } + @Override public void readExternal(@NotNull final Element element) throws InvalidDataException { super.readExternal(element); diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationFactory.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationFactory.java index bf21b28..1fc20b9 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationFactory.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationFactory.java @@ -30,7 +30,7 @@ public OftRunConfigurationFactory( @Override public @NotNull RunConfiguration createTemplateConfiguration(@NotNull final Project project) { - final OftRunConfiguration configuration = new OftRunConfiguration(project, this, "OpenFastTrace"); + final OftRunConfiguration configuration = new OftRunConfiguration(project, this, getName()); this.initializer.accept(configuration); return configuration; } diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationType.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationType.java index 4ac35ff..f3a343b 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationType.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationType.java @@ -28,7 +28,7 @@ public OftRunConfigurationType() { config.updateFrom(snapshot); })); - addFactory(new OftRunConfigurationFactory(this, "Design and down", config -> { + addFactory(new OftRunConfigurationFactory(this, "Design and above", config -> { final OftTraceSettingsSnapshot snapshot = new OftTraceSettingsSnapshot( OftTraceScopeMode.SELECTED_RESOURCES, false, diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunProfileState.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunProfileState.java index c974f5b..d5fef6a 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunProfileState.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunProfileState.java @@ -44,6 +44,7 @@ public OftRunProfileState(final ExecutionEnvironment environment, final OftTrace final String contentTitle = "OpenFastTrace Trace: " + environment.getRunProfile().getName(); final ExecutionPresentation executionPresentation = createExecutionPresentation(project, executor); + // [impl->dsn~trace-action-integration~3] if (!resolution.isValid()) { executionPresentation.outputPresenter() .show(project, contentTitle, OftTraceResult.invalidInput(resolution.errorMessage())); diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceBackgroundRunnerTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceBackgroundRunnerTest.java index c36d30f..01b6abe 100644 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceBackgroundRunnerTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceBackgroundRunnerTest.java @@ -25,6 +25,8 @@ import static org.hamcrest.Matchers.nullValue; class OftTraceBackgroundRunnerTest { + // [itest->dsn~run-trace-project-in-background~2] + // [itest->dsn~trace-action-integration~3] @Test void testGivenTraceTaskWhenRunningThenItUpdatesProgressAndPresentsSuccessfulResult(@TempDir final Path temporaryDirectory) throws Exception { diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceTestRunnerRunContentOutputPresenterTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceTestRunnerRunContentOutputPresenterTest.java index 42ad9f6..3ff1971 100644 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceTestRunnerRunContentOutputPresenterTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceTestRunnerRunContentOutputPresenterTest.java @@ -19,7 +19,7 @@ import static org.hamcrest.Matchers.notNullValue; public class OftTraceTestRunnerRunContentOutputPresenterTest extends AbstractOftPlatformTestCase { - // [itest->dsn~show-trace-project-in-test-runner-ui-by-default~1] + // [itest->dsn~show-trace-result-in-test-runner-ui-by-default~2] public void testGivenTraceResultWhenPresentedThenItShowsTestRunnerRunContent() { final AtomicReference consoleRef = new AtomicReference<>(); final AtomicReference descriptorRef = new AtomicReference<>(); diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java index 0ab205f..c8fef8d 100644 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java @@ -136,7 +136,7 @@ public void testGivenRunConfigurationTypeWhenCheckingFactoriesThenItContainsAllT assertThat(Arrays.asList(factoryNames), containsInAnyOrder( "User requirements", - "Design and down", + "Design and above", "Typical project", "Unfiltered" )); @@ -156,7 +156,7 @@ public void testGivenUserRequirementsTemplateWhenCreatingConfigurationThenItHasC } public void testGivenDesignAndDownTemplateWhenCreatingConfigurationThenItHasCorrectSettings() { - final OftRunConfiguration configuration = createConfigurationFromTemplate("Design and down"); + final OftRunConfiguration configuration = createConfigurationFromTemplate("Design and above"); final OftTraceSettingsSnapshot snapshot = configuration.snapshot(); Assertions.assertAll( @@ -206,6 +206,9 @@ private OftRunConfiguration createConfigurationFromTemplate(final String templat .filter(f -> f.getName().equals(templateName)) .findFirst() .orElseThrow(); - return (OftRunConfiguration) factory.createTemplateConfiguration(getProject()); + final OftRunConfiguration configuration = (OftRunConfiguration) factory.createTemplateConfiguration(getProject()); + configuration.setGeneratedName(); + assertThat(configuration.getName(), is(templateName)); + return configuration; } } diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunProfileStateTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunProfileStateTest.java index 0e70af3..5e8a8f3 100644 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunProfileStateTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunProfileStateTest.java @@ -17,6 +17,7 @@ import static org.hamcrest.Matchers.not; public class OftRunProfileStateTest extends AbstractOftPlatformTestCase { + // [itest->dsn~trace-action-integration~3] public void testExecuteReturnsNotNull() throws Exception { final ExecutionEnvironment environment = createEnvironment(); final OftRunProfileState state = new OftRunProfileState( From 679c31261eb105ec060a09b11a09c690ed58de3c Mon Sep 17 00:00:00 2001 From: redcatbaer Date: Sat, 27 Jun 2026 21:52:51 +0200 Subject: [PATCH 5/9] #37: Removed global configuration. --- doc/demo/plugin-demo.md | 14 +- doc/design/building_block_view.md | 12 +- doc/design/runtime_view.md | 6 +- doc/design/solution_strategy.md | 2 +- doc/system_requirements.md | 30 +-- doc/user_guide.md | 30 +-- .../trace/OftTraceInputResolver.java | 2 +- .../trace/OftTraceProjectConfigurable.java | 100 -------- .../trace/OftTraceProjectSettings.java | 81 ------- .../trace/runconfig/OftRunConfiguration.java | 1 + .../runconfig/OftRunConfigurationType.java | 44 +--- src/main/resources/META-INF/plugin.xml | 6 - .../OftTraceInputResolverPlatformTest.java | 19 +- .../trace/OftTraceInputResolverTest.java | 2 +- .../OftTraceProjectConfigurableTest.java | 218 ------------------ .../trace/OftTraceProjectSettingsTest.java | 41 ---- ...OftRunConfigurationSettingsEditorTest.java | 17 ++ .../runconfig/OftRunConfigurationTest.java | 1 + 18 files changed, 62 insertions(+), 564 deletions(-) delete mode 100644 src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectConfigurable.java delete mode 100644 src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectSettings.java delete mode 100644 src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectConfigurableTest.java delete mode 100644 src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectSettingsTest.java diff --git a/doc/demo/plugin-demo.md b/doc/demo/plugin-demo.md index a122d44..bd9d366 100644 --- a/doc/demo/plugin-demo.md +++ b/doc/demo/plugin-demo.md @@ -7,15 +7,15 @@ This script is for a short live demonstration of the plugin using the isolated e 1. Install the IntelliJ Presenter Plugin. 2. Install the OpenFastTrace IntelliJ plugin from the latest GitHub release as described below, or launch a sandbox IDE with `./gradlew manualTestIde`. 3. Open `doc/demo/example` as the IntelliJ project for the demo. -4. Open `Settings | Tools | OpenFastTrace`, select `Trace selected resources`, clear `Include IntelliJ source directories` and `Include IntelliJ test directories`, and set `Additional project-relative files or directories (one per line)` to: +4. Open `Run | Edit Configurations...`, add an `OpenFastTrace` configuration, select `Trace selected resources`, clear `Include IntelliJ source directories` and `Include IntelliJ test directories`, and set `Additional project-relative files or directories (one per line)` to: ```text doc/demo/example ``` - Apply the settings. The validation area should show no errors. + Apply the configuration. The validation area should show no errors. 5. Open `excuse-of-the-day.md` and `excuse-of-the-day.sh`. -6. Run `Tools | OpenFastTrace | Trace Project` once. The starting demo project should trace green. +6. Run the `OpenFastTrace` configuration once. The starting demo project should trace green. ## Installing the Plugin from GitHub @@ -37,11 +37,11 @@ For a local development build or rehearsal without installing a release artifact > Today we are going to make one tiny change to a tiny project and let the IDE keep track of the requirement trace chain while we work. > We use OpenFastTrace and the IntelliJ plugin to make our life easier. -> The example is deliberately small. But the concepts of working with requirement tracing translates nicely to larger projects. +> The example is deliberately small. But the concept of working with requirement tracing translates nicely to larger projects. ### 1. Show Trace Scope Configuration -Open `Settings | Tools | OpenFastTrace` and show the selected-resource configuration from the preparation: `Trace selected resources`, both IntelliJ directory checkboxes cleared, and the additional paths set to `doc/demo/example`. +Open the `OpenFastTrace` run configuration editor and show the selected-resource configuration from the preparation: `Trace selected resources`, both IntelliJ directory checkboxes cleared, and the additional paths set to `doc/demo/example`. > The demonstration has a narrow scope. A Markdown specification and the shell implementation, both found under a `doc/demo/example` in this project. > Every trace run now checks only the files we want in this example. @@ -50,7 +50,7 @@ Open `Settings | Tools | OpenFastTrace` and show the selected-resource configura Open `excuse-of-the-day.md` and point out the highlighted OFT item IDs, `Needs:`, and `Covers:` entries. -> Let's first take look at a specification file. +> Let's first take a look at a specification file. > This is still plain Markdown. The IDE just stops treating the trace parts like wallpaper, which is helpful to identify OFT specification items in text. ### 3. Find the Existing Feature @@ -100,7 +100,7 @@ Run `Tools | OpenFastTrace | Trace Project`. The trace should be red because `ds In `excuse-of-the-day.sh`, add the coverage tag `# [impl->dsn~homework-excuse~1]`. Type the target side partially and invoke completion after `impl->` to select `dsn~homework-excuse~1`, then point out the highlighted tag. -> The script stays ordinary shell. The OFT tag is a comment for Bash and evidence for the trace. +> The script stays an ordinary shell. The OFT tag is a comment for Bash and evidence for the trace. ### 11. Run the Green Trace and Open the Guide diff --git a/doc/design/building_block_view.md b/doc/design/building_block_view.md index a1d7702..1fed425 100644 --- a/doc/design/building_block_view.md +++ b/doc/design/building_block_view.md @@ -240,7 +240,7 @@ Needs: bld, itest ### Trace Configuration Integration `dsn~trace-configuration-integration~2` -The plugin provides a trace-configuration component that stores OpenFastTrace trace-scope settings per IntelliJ project and through dedicated run configurations. It provides pre-configured templates for common scanning scenarios. It exposes those settings through project configuration UI and the run configuration editor, resolves the selected-resource options and filters into a normalized OpenFastTrace input set and filter criteria, stores the run-configuration result-view selection, treats the IntelliJ Test Runner UI as the result-view default when no selection is stored, and owns the plugin resource used as the OpenFastTrace run-configuration icon. +The plugin provides a trace-configuration component that stores OpenFastTrace trace-scope settings through dedicated run configurations. It provides pre-configured templates for common scanning scenarios. It exposes those settings through the run configuration editor, resolves the selected-resource options and filters into a normalized OpenFastTrace input set and filter criteria, stores the run-configuration result-view selection, treats the IntelliJ Test Runner UI as the result-view default when no selection is stored, and owns the plugin resource used as the OpenFastTrace run-configuration icon. Covers: - `scn~test-runner-as-default-run-configuration-result-view~1` @@ -251,16 +251,6 @@ Covers: Needs: impl, itest -### Configure Trace Scope in Project Settings -`dsn~configure-trace-scope-in-project-settings~1` - -The plugin provides a project-level settings page for OpenFastTrace that allows users to configure the default trace scope for the project. Users can choose between whole-project tracing and selected-resource tracing. For selected-resource tracing, the settings provide a multi-line text field for additional project-relative paths, initialized with a default `doc/` entry. - -Covers: -- `scn~configure-trace-scope-in-project-settings~1` - -Needs: impl, itest - ### Trace Action Integration `dsn~trace-action-integration~3` diff --git a/doc/design/runtime_view.md b/doc/design/runtime_view.md index ccf98bc..6f966b1 100644 --- a/doc/design/runtime_view.md +++ b/doc/design/runtime_view.md @@ -379,7 +379,7 @@ Needs: impl, itest ### Trace Selected Project Resources `dsn~trace-selected-project-resources~2` -**Given** an IntelliJ project is open and OpenFastTrace project settings or run configuration are configured for selected-resource tracing +**Given** an IntelliJ project is open and an OpenFastTrace run configuration is configured for selected-resource tracing **When** a user starts an OpenFastTrace trace **Then** the trace-configuration component resolves only the configured source roots, test roots, and additional project-relative paths and the trace-execution service passes only those inputs to OpenFastTrace. @@ -415,7 +415,7 @@ Needs: impl, itest ### Add Project-Relative Paths to Selected-Resource Trace `dsn~add-project-relative-paths-to-selected-resource-trace~1` -**Given** selected-resource tracing is active and the OpenFastTrace project settings contain additional project-relative paths +**Given** selected-resource tracing is active, and the OpenFastTrace run configuration contains additional project-relative paths **When** the trace-configuration component resolves the effective OpenFastTrace inputs for the opened project **Then** it resolves those paths against the project directory, keeps the valid files and directories as trace inputs, and rejects invalid configured paths before the trace starts. @@ -427,7 +427,7 @@ Needs: impl, itest ### Show Per-Line Validation for Additional Trace Paths `dsn~show-per-line-validation-for-additional-trace-paths~1` -**Given** selected-resource tracing is active and the user edits the multi-line field for additional project-relative trace paths +**Given** selected-resource tracing is active and the user edits the run-configuration field for additional project-relative trace paths **When** the trace-configuration component validates the configured lines against the opened project directory **Then** it keeps the field editable, ignores empty lines, and shows a non-blocking validation hint below the field for each non-empty line that does not resolve to a valid file or directory. diff --git a/doc/design/solution_strategy.md b/doc/design/solution_strategy.md index 8ef903a..59574ac 100644 --- a/doc/design/solution_strategy.md +++ b/doc/design/solution_strategy.md @@ -59,7 +59,7 @@ The next increment extends that editor support with in-process OpenFastTrace tra This phased approach keeps the initial editor support small while still allowing the product to grow into project-level validation. It also limits the first tracing increment to established IDE concepts such as actions, progress indicators, and plain text output before the plugin invests in richer report interpretation such as Problems-view integration. -The trace-path configuration increment keeps that action-centric workflow but moves trace input selection into project-scoped settings. The plugin resolves either the whole project directory or a whitelist-style input set assembled from IntelliJ source roots, IntelliJ test roots, and additional project-relative paths. This matches OpenFastTrace's input model while keeping trace configuration reproducible for a project instead of relying on ad-hoc per-run path selection. +The trace-path configuration increment keeps that action-centric workflow but moves trace input selection into the run configuration editor. The plugin resolves either the whole project directory or a whitelist-style input set assembled from IntelliJ source roots, IntelliJ test roots, and additional project-relative paths. This matches OpenFastTrace's input model while keeping trace configuration reproducible without relying on ad-hoc per-run path selection. ## ANSI-Colored Trace Output diff --git a/doc/system_requirements.md b/doc/system_requirements.md index 05f318d..eb52a6d 100644 --- a/doc/system_requirements.md +++ b/doc/system_requirements.md @@ -344,16 +344,6 @@ Covers: Needs: scn -### Configure Trace Scope in Project Settings -`req~configure-trace-scope-in-project-settings~1` - -The plugin integrates OpenFastTrace trace-scope settings into IntelliJ project configuration. Users can configure whether a trace uses the whole project or only selected resources and can edit the selected-resource paths directly in the IDE settings workflow. - -Covers: -- `feat~run-oft-trace~3` - -Needs: scn - ### Trace Selected Project Resources `req~trace-selected-project-resources~1` @@ -387,7 +377,7 @@ Needs: scn ### Add Project-Relative Paths to Selected-Resource Trace `req~add-project-relative-paths-to-selected-resource-trace~1` -When selected-resource tracing is active, the plugin lets users add additional trace inputs through a multi-line text field in the project settings. Each non-empty line specifies one file or directory path relative to the opened project directory that OpenFastTrace should scan. If the user has not changed that setting, the field contains exactly one default entry: `doc/`. +When selected-resource tracing is active, the plugin lets users add additional trace inputs through a multi-line text field in the run configuration editor. Each non-empty line specifies one file or directory path relative to the opened project directory that OpenFastTrace should scan. If the user has not changed that setting, the field contains exactly one default entry: `doc/`. Covers: - `feat~run-oft-trace~3` @@ -1173,22 +1163,10 @@ Covers: Needs: dsn -### Configure Trace Scope in Project Settings -`scn~configure-trace-scope-in-project-settings~1` - -**Given** an IntelliJ project is open -**When** a user opens the project settings for the OpenFastTrace plugin -**Then** the user can choose whether the default trace scope uses the whole project or only selected resources and, for selected-resource tracing, can edit the additional trace paths in a multi-line project-settings field that contains exactly one default entry, `doc/`, until the user changes it - -Covers: -- `req~configure-trace-scope-in-project-settings~1` - -Needs: dsn - ### Trace Selected Project Resources `scn~trace-selected-project-resources~1` -**Given** an IntelliJ project is open and the OpenFastTrace project settings or run configuration are configured for selected-resource tracing +**Given** an IntelliJ project is open and the OpenFastTrace run configuration is configured for selected-resource tracing **When** a user starts an OpenFastTrace trace **Then** the plugin starts the trace by passing only the resolved selected resources to OpenFastTrace instead of the whole project directory @@ -1225,7 +1203,7 @@ Needs: dsn ### Add Project-Relative Paths to Selected-Resource Trace `scn~add-project-relative-paths-to-selected-resource-trace~1` -**Given** an IntelliJ project is open, selected-resource tracing is active, and the OpenFastTrace project settings or run configuration contains additional project-relative file or directory paths +**Given** an IntelliJ project is open, selected-resource tracing is active, and the OpenFastTrace run configuration contains additional project-relative file or directory paths **When** a user starts an OpenFastTrace trace **Then** the plugin resolves those project-relative files and directories against the opened project and includes them in the effective OpenFastTrace input set @@ -1239,7 +1217,7 @@ Needs: dsn **Given** an IntelliJ project is open, selected-resource tracing is active, and the user edits the multi-line field for additional project-relative trace paths **When** one or more non-empty lines do not resolve to valid files or directories below the opened project directory -**Then** the project settings show a non-blocking validation hint for each invalid line below the field so the user can see which configured paths are not found. +**Then** the run configuration shows a non-blocking validation hint for each invalid line below the field so the user can see which configured paths are not found. Covers: - `req~add-project-relative-paths-to-selected-resource-trace~1` diff --git a/doc/user_guide.md b/doc/user_guide.md index 188b5c4..445d7d7 100644 --- a/doc/user_guide.md +++ b/doc/user_guide.md @@ -127,31 +127,7 @@ Run a project trace from the main menu: The default keyboard shortcut is `Ctrl+Alt+Shift+O`. By default, the action traces the whole opened project and displays results in the IntelliJ Test Runner UI. - -## Configure The Trace Project Action - -Open `Settings | Tools | OpenFastTrace` to configure the global `Trace Project` action. - -![OpenFastTrace trace settings in the IDE settings dialog](user_guide/images/trace-setting.png) - -Choose one trace scope: - -* `Trace the whole project` scans the opened project root. -* `Trace selected resources` scans only the selected source directories, test directories, and additional paths. - -For selected-resource traces, configure these inputs: - -* `Include IntelliJ source directories` -* `Include IntelliJ test directories` -* `Additional project-relative files or directories (one per line)` - -The default additional path is `doc/`. Paths are resolved relative to the opened project root. The settings page validates the entered paths and shows the base directory used for resolution. - -Use `Artifact types:` to limit a trace to comma-separated artifact types such as `feat,req,scn,dsn`. - -Use `Tags:` to limit a trace to comma-separated OFT tags. - -Leave `Artifact types:` or `Tags:` empty to include all artifact types or tags. +Use a run configuration when you need selected-resource tracing, artifact-type filters, tag filters, or plain text output. ## Create OpenFastTrace Run Configurations @@ -163,7 +139,7 @@ Use OpenFastTrace run configurations when you need multiple repeatable trace set 4. Configure the trace scope, artifact types, tags, and result view. 5. Save and run the configuration from the IDE toolbar. -Run configurations use the same trace-scope controls as `Settings | Tools | OpenFastTrace`. +Run configurations provide the same trace-scope controls in the configuration editor. They also let you choose the result view: @@ -222,7 +198,7 @@ For coverage-tag completion, invoke completion on the target side after the arro ### Trace Project Scans Too Much Or Too Little -Open `Settings | Tools | OpenFastTrace` and switch between `Trace the whole project` and `Trace selected resources`. +Open the `OpenFastTrace` run configuration editor and switch between `Trace the whole project` and `Trace selected resources`. For selected resources, verify the source-root checkboxes and the `Additional project-relative files or directories (one per line)` field. The field accepts one file or directory per line. diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolver.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolver.java index 92ef97e..343318e 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolver.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolver.java @@ -25,7 +25,7 @@ private OftTraceInputResolver() { } public static OftTraceInputResolution resolve(final Project project) { - return resolve(project, OftTraceProjectSettings.getInstance(project).snapshot()); + return resolve(project, OftTraceSettingsSnapshot.DEFAULT); } public static OftTraceInputResolution resolve(final Project project, final OftTraceSettingsSnapshot settings) { diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectConfigurable.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectConfigurable.java deleted file mode 100644 index dd89ec1..0000000 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectConfigurable.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.itsallcode.openfasttrace.intellijplugin.trace; - -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.options.SearchableConfigurable; -import com.intellij.openapi.project.Project; -import org.jspecify.annotations.NonNull; - -import javax.swing.JComponent; -import java.nio.file.InvalidPathException; -import java.nio.file.Path; -import java.util.Objects; - -// [impl->dsn~configure-trace-scope-in-project-settings~1] -public final class OftTraceProjectConfigurable implements SearchableConfigurable, Configurable.NoScroll { - private static final Logger LOG = Logger.getInstance(OftTraceProjectConfigurable.class); - static final String ID = "org.itsallcode.openfasttrace.intellijplugin.trace.OftTraceProjectConfigurable"; - - private final Project project; - private OftTraceSettingsComponent component; - - public OftTraceProjectConfigurable(final Project project) { - this.project = project; - } - - @Override - public @NonNull String getId() { - return ID; - } - - @Override - public String getDisplayName() { - return "OpenFastTrace"; - } - - @Override - public JComponent createComponent() { - if (component == null) { - component = new OftTraceSettingsComponent(projectRoot()); - } - return component.getPanel(); - } - - @Override - public boolean isModified() { - return !Objects.equals(component.getSettings(), OftTraceProjectSettings.getInstance(project).snapshot()); - } - - @Override - @SuppressWarnings("java:S1162") // IntelliJ settings validation reports rejected values through this API type. - public void apply() throws ConfigurationException { - validate(component.getSettings()); - OftTraceProjectSettings.getInstance(project).updateFrom(component.getSettings()); - } - - @Override - public void reset() { - component.setSettings(OftTraceProjectSettings.getInstance(project).snapshot()); - } - - @Override - public void disposeUIResources() { - component = null; - } - - // IntelliJ Configurable callers expect ConfigurationException for validation errors. - @SuppressWarnings("java:S1162") - private static void validate(final OftTraceSettingsSnapshot settings) throws ConfigurationException { - for (final String additionalPath : settings.additionalPaths()) { - final Path path; - try { - path = Path.of(additionalPath); - } catch (final InvalidPathException exception) { - LOG.debug("Rejecting invalid OpenFastTrace additional trace path: " + additionalPath, exception); - throw new ConfigurationException( - "Additional trace path is invalid: " + exception.getInput() - ); - } - if (path.isAbsolute()) { - throw new ConfigurationException( - "Additional trace path must be project-relative: " + additionalPath - ); - } - } - } - - private Path projectRoot() { - final String basePath = project.getBasePath(); - if (basePath == null || basePath.isBlank()) { - return null; - } - try { - return Path.of(basePath); - } catch (final InvalidPathException exception) { - LOG.debug("Ignoring invalid OpenFastTrace project base path: " + basePath, exception); - return null; - } - } -} diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectSettings.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectSettings.java deleted file mode 100644 index fbd1388..0000000 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectSettings.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.itsallcode.openfasttrace.intellijplugin.trace; - -import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.Service; -import com.intellij.openapi.components.State; -import com.intellij.openapi.components.Storage; -import com.intellij.openapi.project.Project; - -@Service(Service.Level.PROJECT) -@State( - name = "org.itsallcode.openfasttrace.intellijplugin.trace.OftTraceProjectSettings", - storages = @Storage("openfasttrace.xml") -) -// [impl->dsn~trace-configuration-integration~2] -final class OftTraceProjectSettings implements PersistentStateComponent { - private State state = new State(); - - static OftTraceProjectSettings getInstance(final Project project) { - return project.getService(OftTraceProjectSettings.class); - } - - OftTraceSettingsSnapshot snapshot() { - return new OftTraceSettingsSnapshot( - parseScopeMode(state.traceScopeMode), - state.includeSourceRoots, - state.includeTestRoots, - state.additionalPathsText, - state.artifactTypesText, - state.tagsText - ); - } - - void updateFrom(final OftTraceSettingsSnapshot snapshot) { - state.traceScopeMode = snapshot.scopeMode().name(); - state.includeSourceRoots = snapshot.includeSourceRoots(); - state.includeTestRoots = snapshot.includeTestRoots(); - state.additionalPathsText = snapshot.additionalPathsText(); - state.artifactTypesText = snapshot.artifactTypesText(); - state.tagsText = snapshot.tagsText(); - } - - @Override - public State getState() { - return state; - } - - @Override - public void loadState(final State state) { - this.state = state == null ? new State() : state; - this.state.traceScopeMode = parseScopeMode(this.state.traceScopeMode).name(); - if (this.state.additionalPathsText == null) { - this.state.additionalPathsText = OftTraceSettingsSnapshot.DEFAULT.additionalPathsText(); - } - if (this.state.artifactTypesText == null) { - this.state.artifactTypesText = ""; - } - if (this.state.tagsText == null) { - this.state.tagsText = ""; - } - } - - private static OftTraceScopeMode parseScopeMode(final String value) { - if (value == null || value.isBlank()) { - return OftTraceSettingsSnapshot.DEFAULT.scopeMode(); - } - try { - return OftTraceScopeMode.valueOf(value); - } catch (final IllegalArgumentException ignored) { - return OftTraceSettingsSnapshot.DEFAULT.scopeMode(); - } - } - - static final class State { - String traceScopeMode = OftTraceSettingsSnapshot.DEFAULT.scopeMode().name(); - boolean includeSourceRoots = OftTraceSettingsSnapshot.DEFAULT.includeSourceRoots(); - boolean includeTestRoots = OftTraceSettingsSnapshot.DEFAULT.includeTestRoots(); - String additionalPathsText = OftTraceSettingsSnapshot.DEFAULT.additionalPathsText(); - String artifactTypesText = OftTraceSettingsSnapshot.DEFAULT.artifactTypesText(); - String tagsText = OftTraceSettingsSnapshot.DEFAULT.tagsText(); - } -} diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfiguration.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfiguration.java index 846dddc..29de9fd 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfiguration.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfiguration.java @@ -20,6 +20,7 @@ import java.io.Serializable; +// [impl->dsn~trace-configuration-integration~2] public final class OftRunConfiguration extends LocatableConfigurationBase { private final State state = new State(); diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationType.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationType.java index f3a343b..d842b46 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationType.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationType.java @@ -8,62 +8,34 @@ import org.itsallcode.openfasttrace.intellijplugin.trace.OftTraceSettingsSnapshot; // [impl->dsn~openfasttrace-run-configuration~2] +// [impl->dsn~use-run-configuration-templates~1] public final class OftRunConfigurationType extends ConfigurationTypeBase { public static final String ID = "OpenFastTraceRunConfiguration"; public OftRunConfigurationType() { super(ID, "OpenFastTrace", "OpenFastTrace run configuration", NotNullLazyValue.createValue(() -> OftIcons.OPEN_FAST_TRACE)); - addFactory(new OftRunConfigurationFactory(this, "User requirements", config -> { final OftTraceSettingsSnapshot snapshot = new OftTraceSettingsSnapshot( - OftTraceScopeMode.SELECTED_RESOURCES, - false, - false, - "doc/", - "feat, req, scn, bconstr", - "", - OftTraceResultView.TEST_RUNNER - ); + OftTraceScopeMode.SELECTED_RESOURCES, false, false, "doc/", "feat, req, scn, bconstr", "", + OftTraceResultView.TEST_RUNNER); config.updateFrom(snapshot); })); - addFactory(new OftRunConfigurationFactory(this, "Design and above", config -> { final OftTraceSettingsSnapshot snapshot = new OftTraceSettingsSnapshot( - OftTraceScopeMode.SELECTED_RESOURCES, - false, - false, - "doc/", - "feat, req, scn, bconstr, arch, dsn, constr, bld", - "", - OftTraceResultView.TEST_RUNNER - ); + OftTraceScopeMode.SELECTED_RESOURCES, false, false, "doc/", + "feat, req, scn, bconstr, arch, dsn, constr, bld", "", OftTraceResultView.TEST_RUNNER); config.updateFrom(snapshot); })); - addFactory(new OftRunConfigurationFactory(this, "Typical project", config -> { final OftTraceSettingsSnapshot snapshot = new OftTraceSettingsSnapshot( - OftTraceScopeMode.SELECTED_RESOURCES, - true, - true, - "doc/", - "", - "", - OftTraceResultView.TEST_RUNNER - ); + OftTraceScopeMode.SELECTED_RESOURCES, true, true, "doc/", "", "", + OftTraceResultView.TEST_RUNNER); config.updateFrom(snapshot); })); - addFactory(new OftRunConfigurationFactory(this, "Unfiltered", config -> { final OftTraceSettingsSnapshot snapshot = new OftTraceSettingsSnapshot( - OftTraceScopeMode.WHOLE_PROJECT, - false, - false, - ".", - "", - "", - OftTraceResultView.TEST_RUNNER - ); + OftTraceScopeMode.WHOLE_PROJECT, false, false, ".", "", "", OftTraceResultView.TEST_RUNNER); config.updateFrom(snapshot); })); } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 2e40110..1d9eb21 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -129,12 +129,6 @@ language="TEXT" implementation="org.itsallcode.openfasttrace.intellijplugin.navigation.OftCoverageTagReferenceContributor"/> - diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolverPlatformTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolverPlatformTest.java index 773f153..1b2535b 100644 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolverPlatformTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolverPlatformTest.java @@ -9,6 +9,7 @@ import com.intellij.openapi.vfs.VirtualFile; import org.itsallcode.openfasttrace.intellijplugin.AbstractOftPlatformTestCase; +import java.io.IOException; import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; @@ -62,12 +63,20 @@ public void testWhenResolvingFromGuessedProjectDirectoryThenItReturnsAResolution assertThat(resolution.map(OftTraceInputResolution::isValid).orElse(true), is(true)); } - public void testWhenResolvingProjectThenItUsesProjectSettings() { - OftTraceProjectSettings.getInstance(getProject()).loadState(new OftTraceProjectSettings.State()); - - final OftTraceInputResolution resolution = OftTraceInputResolver.resolve(getProject()); + public void testWhenResolvingProjectThenItUsesDefaultSettings() + throws IOException, ReflectiveOperationException { + final Path projectRoot = createManagedTestArtifactDirectory("trace-input-resolver-project-root"); + final OftTraceInputResolution resolution = resolveFromProjectRoot( + getProject(), + projectRoot, + OftTraceSettingsSnapshot.DEFAULT + ); - assertNotNull(resolution); + assertThat(resolution.isValid(), is(true)); + assertThat( + resolution.inputs().inputPaths(), + contains(projectRoot) + ); } private void configureModuleRoots(final Path contentRoot, final Path sourceDirectory, final Path testDirectory) { diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolverTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolverTest.java index 2d22d43..1b8374e 100644 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolverTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolverTest.java @@ -110,7 +110,7 @@ void testGivenInvalidBasePathStringWhenResolvingProjectRootThenItReturnsAnInvali } @Test - void testGivenWholeProjectSettingsWhenResolvingThenItUsesTheProjectBasePath( + void testGivenWholeProjectConfigWhenResolvingThenItUsesTheProjectBasePath( @TempDir final Path temporaryDirectory ) { final Project project = projectProxy(temporaryDirectory.toString(), null, "trace-project"); diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectConfigurableTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectConfigurableTest.java deleted file mode 100644 index 4b6d50d..0000000 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectConfigurableTest.java +++ /dev/null @@ -1,218 +0,0 @@ -package org.itsallcode.openfasttrace.intellijplugin.trace; - -import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.project.Project; -import org.itsallcode.openfasttrace.intellijplugin.AbstractOftPlatformTestCase; -import org.junit.jupiter.api.Assertions; - -import javax.swing.JComponent; - -public class OftTraceProjectConfigurableTest extends AbstractOftPlatformTestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - OftTraceProjectSettings.getInstance(getProject()).loadState(new OftTraceProjectSettings.State()); - } - - // [itest->dsn~configure-trace-scope-in-project-settings~1] - public void testGivenDefaultSettingsWhenResettingConfigurableThenItShowsTheDocumentedDefaults() { - final OftTraceProjectConfigurable configurable = new OftTraceProjectConfigurable(getProject()); - configurable.createComponent(); - - configurable.reset(); - - final OftTraceSettingsSnapshot settings = configurableSettings(configurable); - assertEquals(OftTraceSettingsSnapshot.DEFAULT.scopeMode(), settings.scopeMode()); - assertEquals(OftTraceSettingsSnapshot.DEFAULT.includeSourceRoots(), settings.includeSourceRoots()); - assertEquals(OftTraceSettingsSnapshot.DEFAULT.includeTestRoots(), settings.includeTestRoots()); - assertEquals(OftTraceSettingsSnapshot.DEFAULT.additionalPathsText(), settings.additionalPathsText()); - } - - public void testGivenDefaultSettingsWhenResettingConfigurableThenSelectedResourceControlsAreDisabled() { - final OftTraceProjectConfigurable configurable = new OftTraceProjectConfigurable(getProject()); - configurable.createComponent(); - - configurable.reset(); - - assertFalse(component(configurable).isSelectedResourcesEnabled()); - } - - public void testGivenSelectedResourceSettingsWhenApplyingConfigurableThenItUpdatesTheProjectSettings() - throws ConfigurationException { - final OftTraceProjectConfigurable configurable = new OftTraceProjectConfigurable(getProject()); - configurable.createComponent(); - component(configurable).setSettings(new OftTraceSettingsSnapshot( - OftTraceScopeMode.SELECTED_RESOURCES, - true, - false, - "doc/\nspec/", - "", - "" - )); - - assertTrue(configurable.isModified()); - configurable.apply(); - - final OftTraceSettingsSnapshot snapshot = OftTraceProjectSettings.getInstance(getProject()).snapshot(); - assertEquals(OftTraceScopeMode.SELECTED_RESOURCES, snapshot.scopeMode()); - assertTrue(snapshot.includeSourceRoots()); - assertFalse(snapshot.includeTestRoots()); - assertEquals("doc/\nspec/", snapshot.additionalPathsText()); - } - - public void testGivenAbsoluteAdditionalPathWhenApplyingConfigurableThenItRejectsTheSettings() { - final OftTraceProjectConfigurable configurable = new OftTraceProjectConfigurable(getProject()); - configurable.createComponent(); - component(configurable).setSettings(new OftTraceSettingsSnapshot( - OftTraceScopeMode.SELECTED_RESOURCES, - true, - true, - "/absolute/path", - "", - "" - )); - - final ConfigurationException exception = - Assertions.assertThrows(ConfigurationException.class, configurable::apply); - - assertTrue(exception.getLocalizedMessage().contains("must be project-relative")); - } - - public void testGivenInvalidAdditionalPathWhenApplyingConfigurableThenItRejectsTheSettings() { - final OftTraceProjectConfigurable configurable = new OftTraceProjectConfigurable(getProject()); - configurable.createComponent(); - component(configurable).setSettings(new OftTraceSettingsSnapshot( - OftTraceScopeMode.SELECTED_RESOURCES, - true, - true, - "bad\0path", - "", - "" - )); - - final ConfigurationException exception = - Assertions.assertThrows(ConfigurationException.class, configurable::apply); - - assertTrue(exception.getLocalizedMessage().contains("Additional trace path is invalid")); - } - - public void testWhenReadingConfigurableMetadataThenItReturnsTheRegisteredName() { - final OftTraceProjectConfigurable configurable = new OftTraceProjectConfigurable(getProject()); - - assertEquals(OftTraceProjectConfigurable.ID, configurable.getId()); - assertEquals("OpenFastTrace", configurable.getDisplayName()); - } - - public void testWhenDisposingConfigurableThenItReleasesTheComponent() { - final OftTraceProjectConfigurable configurable = new OftTraceProjectConfigurable(getProject()); - final JComponent firstComponent = configurable.createComponent(); - - configurable.disposeUIResources(); - final JComponent secondComponent = configurable.createComponent(); - - assertNotSame(firstComponent, secondComponent); - } - - // [itest->dsn~show-per-line-validation-for-additional-trace-paths~1] - public void testGivenSelectedResourceSettingsWithMissingPathWhenResettingConfigurableThenItShowsPerLineValidation() - throws Exception { - final var validationRoot = createManagedTestArtifactDirectory("trace-settings-validation-root"); - final Project project = projectProxy(validationRoot.toString(), "validation-project"); - OftTraceProjectSettings.getInstance(project).updateFrom(new OftTraceSettingsSnapshot( - OftTraceScopeMode.SELECTED_RESOURCES, - true, - true, - "doc/\nmissing", - "", - "" - )); - final OftTraceProjectConfigurable configurable = new OftTraceProjectConfigurable(project); - configurable.createComponent(); - - configurable.reset(); - - assertEquals( - "Resolved relative to: " + validationRoot.toAbsolutePath().normalize(), - component(configurable).resolvedRelativeToText() - ); - assertTrue(component(configurable).validationMessagesText().contains("Line 1: 'doc/' not found")); - assertTrue(component(configurable).validationMessagesText().contains("Line 2: 'missing' not found")); - } - - public void testGivenWholeProjectModeWhenResettingConfigurableThenItDoesNotShowPerLineValidation() { - final OftTraceProjectConfigurable configurable = new OftTraceProjectConfigurable(getProject()); - configurable.createComponent(); - - configurable.reset(); - - assertEquals("", component(configurable).resolvedRelativeToText()); - assertEquals("", component(configurable).validationMessagesText()); - } - - public void testGivenBlankProjectBasePathWhenShowingSelectedResourceSettingsThenItDoesNotShowValidationRoot() { - final Project project = projectProxy(" ", "blank-root-project"); - final OftTraceProjectConfigurable configurable = new OftTraceProjectConfigurable(project); - configurable.createComponent(); - - component(configurable).setSettings(new OftTraceSettingsSnapshot( - OftTraceScopeMode.SELECTED_RESOURCES, - OftTraceSettingsSnapshot.DEFAULT.includeSourceRoots(), - OftTraceSettingsSnapshot.DEFAULT.includeTestRoots(), - OftTraceSettingsSnapshot.DEFAULT.additionalPathsText(), - OftTraceSettingsSnapshot.DEFAULT.artifactTypesText(), - OftTraceSettingsSnapshot.DEFAULT.tagsText() - )); - - assertEquals("", component(configurable).resolvedRelativeToText()); - assertEquals("", component(configurable).validationMessagesText()); - } - - public void testGivenInvalidProjectBasePathWhenShowingSelectedResourceSettingsThenItDoesNotShowValidationRoot() { - final Project project = projectProxy("bad\0path", "invalid-root-project"); - final OftTraceProjectConfigurable configurable = new OftTraceProjectConfigurable(project); - configurable.createComponent(); - - component(configurable).setSettings(new OftTraceSettingsSnapshot( - OftTraceScopeMode.SELECTED_RESOURCES, - OftTraceSettingsSnapshot.DEFAULT.includeSourceRoots(), - OftTraceSettingsSnapshot.DEFAULT.includeTestRoots(), - OftTraceSettingsSnapshot.DEFAULT.additionalPathsText(), - OftTraceSettingsSnapshot.DEFAULT.artifactTypesText(), - OftTraceSettingsSnapshot.DEFAULT.tagsText() - )); - - assertEquals("", component(configurable).resolvedRelativeToText()); - assertEquals("", component(configurable).validationMessagesText()); - } - - private static OftTraceSettingsSnapshot configurableSettings(final OftTraceProjectConfigurable configurable) { - return component(configurable).getSettings(); - } - - private Project projectProxy(final String basePath, final String name) { - return (Project) java.lang.reflect.Proxy.newProxyInstance( - Project.class.getClassLoader(), - new Class[]{Project.class}, - (proxy, method, args) -> switch (method.getName()) { - case "getBasePath" -> basePath; - case "getName" -> name; - case "getService" -> getProject().getService((Class) args[0]); - case "isDisposed" -> false; - case "equals" -> proxy == args[0]; - case "hashCode" -> System.identityHashCode(proxy); - case "toString" -> "Project[" + name + "]"; - default -> throw new UnsupportedOperationException(method.getName()); - } - ); - } - - private static OftTraceSettingsComponent component(final OftTraceProjectConfigurable configurable) { - try { - final var field = OftTraceProjectConfigurable.class.getDeclaredField("component"); - field.setAccessible(true); - return (OftTraceSettingsComponent) field.get(configurable); - } catch (final ReflectiveOperationException exception) { - throw new IllegalStateException("Failed to access configurable component", exception); - } - } -} diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectSettingsTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectSettingsTest.java deleted file mode 100644 index 903378d..0000000 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceProjectSettingsTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.itsallcode.openfasttrace.intellijplugin.trace; - -import org.itsallcode.openfasttrace.intellijplugin.AbstractOftPlatformTestCase; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; - -public class OftTraceProjectSettingsTest extends AbstractOftPlatformTestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - OftTraceProjectSettings.getInstance(getProject()).loadState(new OftTraceProjectSettings.State()); - } - - public void testGivenFreshProjectSettingsWhenReadingThenItReturnsTheDocumentedDefaults() { - final OftTraceSettingsSnapshot snapshot = OftTraceProjectSettings.getInstance(getProject()).snapshot(); - - assertThat(snapshot.scopeMode(), is(OftTraceSettingsSnapshot.DEFAULT.scopeMode())); - assertThat(snapshot.includeSourceRoots(), is(OftTraceSettingsSnapshot.DEFAULT.includeSourceRoots())); - assertThat(snapshot.includeTestRoots(), is(OftTraceSettingsSnapshot.DEFAULT.includeTestRoots())); - assertThat(snapshot.additionalPathsText(), is(OftTraceSettingsSnapshot.DEFAULT.additionalPathsText())); - assertThat(snapshot.resultView(), is(OftTraceSettingsSnapshot.DEFAULT.resultView())); - } - - public void testGivenStoredStateWhenLoadingThenItNormalizesTheSnapshot() { - final OftTraceProjectSettings settings = OftTraceProjectSettings.getInstance(getProject()); - final OftTraceProjectSettings.State state = new OftTraceProjectSettings.State(); - state.traceScopeMode = OftTraceScopeMode.SELECTED_RESOURCES.name(); - state.includeSourceRoots = false; - state.includeTestRoots = true; - state.additionalPathsText = "spec/\ndoc/"; - - settings.loadState(state); - - final OftTraceSettingsSnapshot snapshot = settings.snapshot(); - assertThat(snapshot.scopeMode(), is(OftTraceScopeMode.SELECTED_RESOURCES)); - assertThat(snapshot.includeSourceRoots(), is(false)); - assertThat(snapshot.includeTestRoots(), is(true)); - assertThat(snapshot.additionalPathsText(), is("spec/\ndoc/")); - } -} diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationSettingsEditorTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationSettingsEditorTest.java index 684eb32..05d287d 100644 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationSettingsEditorTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationSettingsEditorTest.java @@ -9,6 +9,7 @@ import javax.swing.JComponent; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; @@ -87,6 +88,22 @@ public void testGivenEditorWhenApplyingToConfigurationThenItUpdatesConfiguration ); } + // [itest->dsn~show-per-line-validation-for-additional-trace-paths~1] + public void testGivenEditorWithMissingAdditionalPathWhenUpdatingSettingsThenItShowsPerLineValidation() { + editor.createEditor(); // Initialize component + editor.component.setSettings(new OftTraceSettingsSnapshot( + OftTraceScopeMode.SELECTED_RESOURCES, + true, + true, + "missing", + "", + "", + OftTraceResultView.TEST_RUNNER + )); + + assertThat(editor.component.validationMessagesText(), containsString("Line 1: 'missing' not found")); + } + private OftRunConfiguration createConfiguration(final String name) { final OftRunConfigurationType type = new OftRunConfigurationType(); final OftRunConfigurationFactory factory = (OftRunConfigurationFactory) type.getConfigurationFactories()[0]; diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java index c8fef8d..3e5a72c 100644 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java @@ -128,6 +128,7 @@ public void testGivenRunConfigurationTypeWhenReadingIconThenItUsesTheOpenFastTra ); } + // [itest->dsn~use-run-configuration-templates~1] public void testGivenRunConfigurationTypeWhenCheckingFactoriesThenItContainsAllTemplates() { final OftRunConfigurationType type = new OftRunConfigurationType(); final String[] factoryNames = Arrays.stream(type.getConfigurationFactories()) From 6aa33627378af7156c55c3688aab37ec3e1ebc1b Mon Sep 17 00:00:00 2001 From: redcatbaer Date: Sat, 27 Jun 2026 21:53:52 +0200 Subject: [PATCH 6/9] #37: Fixed potential null problem. --- .../intellijplugin/trace/runconfig/OftRunConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfiguration.java b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfiguration.java index 29de9fd..cb5b6ee 100644 --- a/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfiguration.java +++ b/src/main/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfiguration.java @@ -19,6 +19,7 @@ import org.jspecify.annotations.NonNull; import java.io.Serializable; +import java.util.Objects; // [impl->dsn~trace-configuration-integration~2] public final class OftRunConfiguration extends LocatableConfigurationBase { @@ -65,7 +66,7 @@ public void updateFrom(final OftTraceSettingsSnapshot snapshot) { @Override public String suggestedName() { - return getFactory().getName(); + return Objects.requireNonNull(getFactory()).getName(); } @Override From 9df849c5f265a632f2bebb2bd46e65c5a5bfc914 Mon Sep 17 00:00:00 2001 From: redcatbaer Date: Sat, 27 Jun 2026 22:11:23 +0200 Subject: [PATCH 7/9] #37: Fixed broken build. --- .idea/sonarlint.xml | 8 ++++++++ doc/changes/changes_0.9.0.md | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 .idea/sonarlint.xml diff --git a/.idea/sonarlint.xml b/.idea/sonarlint.xml new file mode 100644 index 0000000..cfb6719 --- /dev/null +++ b/.idea/sonarlint.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/doc/changes/changes_0.9.0.md b/doc/changes/changes_0.9.0.md index fbc4f51..9d469e1 100644 --- a/doc/changes/changes_0.9.0.md +++ b/doc/changes/changes_0.9.0.md @@ -1,6 +1,6 @@ # OpenFastTrace IntelliJ Plugin 0.9.0, released 2026-06-27 -Version 0.9.0 introduces specialized run configuration templates and simplifies the plugin UI by removing the redundant global trace menu. +Version 0.9.0 introduces specialized run configuration templates and improves the metadata shown by JetBrains plugin surfaces. Before installing or updating the plugin, users can now see a clearer overview of what OpenFastTrace support does in the IDE and read the current release notes from the maintained project changelog. Users can now quickly set up common OpenFastTrace scanning scenarios using pre-configured templates when creating a new run configuration: * **User requirements**: Scans `doc/` for core artifact types (`feat, req, scn, bconstr`). @@ -17,3 +17,7 @@ OpenFastTrace 4.5.0 ## Features * #61: Replace global OFT scan with specialized run configuration templates + +## Documentation + +* #51: Complete Marketplace-facing plugin metadata From 302fba4e7bcac277666e70ded01dfc489dcfd3dd Mon Sep 17 00:00:00 2001 From: redcatbaer Date: Sat, 27 Jun 2026 22:38:19 +0200 Subject: [PATCH 8/9] #37: Turned four similar tests into a parameterized one. --- .../runconfig/OftRunConfigurationTest.java | 83 +++++++++---------- 1 file changed, 37 insertions(+), 46 deletions(-) diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java index 3e5a72c..90932a2 100644 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/runconfig/OftRunConfigurationTest.java @@ -11,6 +11,10 @@ import org.itsallcode.openfasttrace.intellijplugin.trace.OftTraceSettingsSnapshot; import org.jdom.Element; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import java.util.Arrays; @@ -22,6 +26,16 @@ // [itest->dsn~openfasttrace-run-configuration~2] public class OftRunConfigurationTest extends AbstractOftPlatformTestCase { + @BeforeEach + void initPlatformFixture() throws Exception { + super.setUp(); + } + + @AfterEach + void releasePlatformFixture() throws Exception { + super.tearDown(); + } + // [itest->dsn~test-runner-as-default-run-configuration-result-view~1] // [itest->dsn~trace-configuration-integration~2] public void testGivenNewRunConfigurationWhenReadingSnapshotThenItDefaultsToTestRunner() { @@ -143,55 +157,32 @@ public void testGivenRunConfigurationTypeWhenCheckingFactoriesThenItContainsAllT )); } - public void testGivenUserRequirementsTemplateWhenCreatingConfigurationThenItHasCorrectSettings() { - final OftRunConfiguration configuration = createConfigurationFromTemplate("User requirements"); - final OftTraceSettingsSnapshot snapshot = configuration.snapshot(); - - Assertions.assertAll( - () -> assertThat(snapshot.scopeMode(), is(OftTraceScopeMode.SELECTED_RESOURCES)), - () -> assertThat(snapshot.includeSourceRoots(), is(false)), - () -> assertThat(snapshot.includeTestRoots(), is(false)), - () -> assertThat(snapshot.additionalPathsText(), is("doc/")), - () -> assertThat(snapshot.artifactTypesText(), is("feat, req, scn, bconstr")) - ); - } - - public void testGivenDesignAndDownTemplateWhenCreatingConfigurationThenItHasCorrectSettings() { - final OftRunConfiguration configuration = createConfigurationFromTemplate("Design and above"); - final OftTraceSettingsSnapshot snapshot = configuration.snapshot(); - - Assertions.assertAll( - () -> assertThat(snapshot.scopeMode(), is(OftTraceScopeMode.SELECTED_RESOURCES)), - () -> assertThat(snapshot.includeSourceRoots(), is(false)), - () -> assertThat(snapshot.includeTestRoots(), is(false)), - () -> assertThat(snapshot.additionalPathsText(), is("doc/")), - () -> assertThat(snapshot.artifactTypesText(), is("feat, req, scn, bconstr, arch, dsn, constr, bld")) - ); - } - - public void testGivenTypicalProjectTemplateWhenCreatingConfigurationThenItHasCorrectSettings() { - final OftRunConfiguration configuration = createConfigurationFromTemplate("Typical project"); - final OftTraceSettingsSnapshot snapshot = configuration.snapshot(); - - Assertions.assertAll( - () -> assertThat(snapshot.scopeMode(), is(OftTraceScopeMode.SELECTED_RESOURCES)), - () -> assertThat(snapshot.includeSourceRoots(), is(true)), - () -> assertThat(snapshot.includeTestRoots(), is(true)), - () -> assertThat(snapshot.additionalPathsText(), is("doc/")), - () -> assertThat(snapshot.artifactTypesText(), is("")) - ); - } - - public void testGivenUnfilteredTemplateWhenCreatingConfigurationThenItHasCorrectSettings() { - final OftRunConfiguration configuration = createConfigurationFromTemplate("Unfiltered"); + @ParameterizedTest(name = "{0}") + @CsvSource({ + "'User requirements', false, false, false, 'doc/', 'feat, req, scn, bconstr'", + "'Design and above', false, false, false, 'doc/', 'feat, req, scn, bconstr, arch, dsn, constr, bld'", + "'Typical project', false, true, true, 'doc/', ''", + "'Unfiltered', true, false, false, '.', ''" + }) + void testGivenRunConfigurationTemplateWhenCreatingConfigurationThenItHasCorrectSettings( + final String templateName, + final boolean wholeProject, + final boolean includeSourceRoots, + final boolean includeTestRoots, + final String additionalPathsText, + final String artifactTypesText + ) { + final OftRunConfiguration configuration = createConfigurationFromTemplate(templateName); final OftTraceSettingsSnapshot snapshot = configuration.snapshot(); Assertions.assertAll( - () -> assertThat(snapshot.scopeMode(), is(OftTraceScopeMode.WHOLE_PROJECT)), - () -> assertThat(snapshot.includeSourceRoots(), is(false)), - () -> assertThat(snapshot.includeTestRoots(), is(false)), - () -> assertThat(snapshot.additionalPathsText(), is(".")), - () -> assertThat(snapshot.artifactTypesText(), is("")) + () -> assertThat(snapshot.scopeMode(), is(wholeProject + ? OftTraceScopeMode.WHOLE_PROJECT + : OftTraceScopeMode.SELECTED_RESOURCES)), + () -> assertThat(snapshot.includeSourceRoots(), is(includeSourceRoots)), + () -> assertThat(snapshot.includeTestRoots(), is(includeTestRoots)), + () -> assertThat(snapshot.additionalPathsText(), is(additionalPathsText)), + () -> assertThat(snapshot.artifactTypesText(), is(artifactTypesText)) ); } From 208b00cc4b1154f9f666d48d8ef244edd90a2b60 Mon Sep 17 00:00:00 2001 From: redcatbaer Date: Sat, 27 Jun 2026 22:42:40 +0200 Subject: [PATCH 9/9] #37: Added test coverage. --- .../trace/OftTraceInputResolverTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolverTest.java b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolverTest.java index 1b8374e..f8eed5f 100644 --- a/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolverTest.java +++ b/src/test/java/org/itsallcode/openfasttrace/intellijplugin/trace/OftTraceInputResolverTest.java @@ -127,6 +127,23 @@ void testGivenWholeProjectConfigWhenResolvingThenItUsesTheProjectBasePath( ); } + @Test + void testGivenWholeProjectResolveWhenUsingDefaultSettingsThenItUsesTheProjectBasePath( + @TempDir final Path temporaryDirectory + ) { + final Project project = projectProxy(temporaryDirectory.toString(), null, "trace-project"); + + final OftTraceInputResolution resolution = OftTraceInputResolver.resolve(project); + + Assertions.assertAll( + () -> assertThat(resolution.isValid(), is(true)), + () -> assertThat(resolution.inputs().isWholeProject(), is(true)), + () -> assertThat(resolution.inputs().inputPaths(), contains(temporaryDirectory)), + () -> assertThat(resolution.inputs().artifactTypes(), is(java.util.List.of())), + () -> assertThat(resolution.inputs().tags(), is(java.util.List.of())) + ); + } + @Test void testGivenInvalidBasePathAndValidProjectFilePathWhenResolvingThenItUsesTheProjectFileParent( @TempDir final Path temporaryDirectory