YamlConfig.java

1
package org.egothor.methodatlas;
2
3
import java.io.IOException;
4
import java.nio.file.Path;
5
import java.util.List;
6
import java.util.Map;
7
8
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
9
import com.fasterxml.jackson.annotation.JsonProperty;
10
import com.fasterxml.jackson.databind.DeserializationFeature;
11
import com.fasterxml.jackson.databind.ObjectMapper;
12
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
13
14
/**
15
 * Loads a YAML configuration file that provides default values for
16
 * command-line options.
17
 *
18
 * <p>
19
 * When a {@code -config <file>} argument is present, {@link CliArgs} calls
20
 * {@link #load(Path)} before processing the remaining arguments. The returned
21
 * {@link YamlConfigFile} seeds the initial values; any matching command-line
22
 * flag then overrides the YAML value.
23
 * </p>
24
 *
25
 * <h2>Supported fields</h2>
26
 *
27
 * <pre>
28
 * outputMode: csv          # csv | plain | sarif  (default: csv)
29
 * emitMetadata: false      # (default: false)
30
 * contentHash: false       # (default: false)
31
 * securityOnly: false      # (default: false)
32
 * includeNonSecurity: false  # opt-in: include non-security methods in SARIF output (default: false)
33
 * sarifOmitScores: false   # opt-out: omit interaction score / confidence from SARIF message text (default: false)
34
 * driftDetect: false       # (default: false)
35
 * overrideFile: .methodatlas-overrides.yaml  # optional
36
 * fileSuffixes:
37
 *   - Test.java
38
 * testMarkers:             # annotation/attribute names; empty = provider defaults
39
 *   - Test
40
 *   - ParameterizedTest
41
 * properties:              # plugin-specific key/multi-value pairs (optional)
42
 *   functionNames:         # example: for a Jest/Mocha/Vitest TypeScript plugin
43
 *     - test
44
 *     - it
45
 * ai:
46
 *   enabled: true
47
 *   provider: ollama       # auto | ollama | openai | openrouter | anthropic | azure_openai | groq | xai | github_models | mistral
48
 *   model: qwen2.5-coder:7b
49
 *   baseUrl: http://localhost:11434
50
 *   apiKey: sk-...
51
 *   apiKeyEnv: MY_KEY_ENV
52
 *   taxonomyFile: /path/to/taxonomy.txt
53
 *   taxonomyMode: default  # default | optimized
54
 *   maxClassChars: 100000
55
 *   timeoutSec: 30
56
 *   maxRetries: 3
57
 *   confidence: false
58
 *   apiVersion: 2024-02-01 # Azure OpenAI REST API version (azure_openai only)
59
 * </pre>
60
 *
61
 * <p>
62
 * Unknown fields in the YAML file are silently ignored.
63
 * </p>
64
 *
65
 * @see CliArgs
66
 */
67
final class YamlConfig {
68
69
    /**
70
     * Prevents instantiation of this utility class.
71
     */
72
    private YamlConfig() {
73
    }
74
75
    /**
76
     * Loads a YAML configuration file.
77
     *
78
     * @param configFile path to the YAML file
79
     * @return parsed configuration; never {@code null}
80
     * @throws IOException              if the file cannot be read
81
     * @throws IllegalArgumentException if the file cannot be parsed as valid YAML
82
     */
83
    /* default */ static YamlConfigFile load(Path configFile) throws IOException {
84
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
85
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
86 1 1. load : replaced return value with null for org/egothor/methodatlas/YamlConfig::load → KILLED
        return mapper.readValue(configFile.toFile(), YamlConfigFile.class);
87
    }
88
89
    // -------------------------------------------------------------------------
90
    // POJO classes
91
    // -------------------------------------------------------------------------
92
93
    /**
94
     * Top-level YAML configuration structure.
95
     */
96
    @JsonIgnoreProperties(ignoreUnknown = true)
97
    /* default */ static final class YamlConfigFile {
98
99
        /** Output mode: {@code csv}, {@code plain}, or {@code sarif}. */
100
        @JsonProperty("outputMode")
101
        /* default */ String outputMode;
102
103
        /** Whether to emit {@code # key: value} metadata comment lines. */
104
        @JsonProperty("emitMetadata")
105
        /* default */ boolean emitMetadata;
106
107
        /** File name suffixes used to select test source files. */
108
        @JsonProperty("fileSuffixes")
109
        /* default */ List<String> fileSuffixes;
110
111
        /**
112
         * Language-neutral test-marker identifiers (annotation/attribute simple
113
         * names for JVM and .NET providers; ignored by TypeScript providers).
114
         * Empty or absent means "use provider defaults".
115
         */
116
        @JsonProperty("testMarkers")
117
        /* default */ List<String> testMarkers;
118
119
        /**
120
         * Plugin-specific key/multi-value pairs forwarded verbatim to each
121
         * {@link org.egothor.methodatlas.api.TestDiscovery} provider.
122
         * Providers ignore keys they do not recognise.
123
         */
124
        @JsonProperty("properties")
125
        /* default */ Map<String, List<String>> properties;
126
127
        /**
128
         * Whether to include a SHA-256 content-hash fingerprint of each class
129
         * source as a {@code content_hash} column.
130
         */
131
        @JsonProperty("contentHash")
132
        /* default */ boolean contentHash;
133
134
        /**
135
         * Path to a YAML classification override file. When set, human-authored
136
         * corrections are applied after AI classification on every run.
137
         */
138
        @JsonProperty("overrideFile")
139
        /* default */ String overrideFile;
140
141
        /**
142
         * When {@code true}, only security-relevant methods are emitted; all
143
         * other methods are silently dropped from the output.
144
         */
145
        @JsonProperty("securityOnly")
146
        /* default */ boolean securityOnly;
147
148
        /**
149
         * When {@code true}, non-security methods are included in SARIF output
150
         * even though SARIF mode applies the security-only filter by default.
151
         * Has no effect in CSV or plain-text modes.
152
         */
153
        @JsonProperty("includeNonSecurity")
154
        /* default */ boolean includeNonSecurity;
155
156
        /**
157
         * When {@code true}, a {@code tag_ai_drift} column is added to CSV/plain
158
         * output comparing the source-level {@code @Tag("security")} annotation
159
         * against the AI security-relevance classification.
160
         */
161
        @JsonProperty("driftDetect")
162
        /* default */ boolean driftDetect;
163
164
        /**
165
         * When {@code true}, the interaction score and confidence percentage are
166
         * omitted from SARIF result message text. Use this when the consuming
167
         * system already renders the {@code properties} bag and the extra text is
168
         * unwanted. Default: {@code false} (scores are embedded in messages).
169
         */
170
        @JsonProperty("sarifOmitScores")
171
        /* default */ boolean sarifOmitScores;
172
173
        /** AI enrichment settings. */
174
        @JsonProperty("ai")
175
        /* default */ YamlAiConfig ai;
176
    }
177
178
    /**
179
     * AI subsystem configuration within the YAML file.
180
     */
181
    @JsonIgnoreProperties(ignoreUnknown = true)
182
    /* default */ static final class YamlAiConfig {
183
184
        /** Whether AI enrichment is enabled. */
185
        @JsonProperty("enabled")
186
        /* default */ Boolean enabled;
187
188
        /**
189
         * AI provider: {@code auto}, {@code ollama}, {@code openai},
190
         * {@code openrouter}, {@code anthropic}, {@code azure_openai},
191
         * {@code groq}, {@code xai}, {@code github_models}, or {@code mistral}.
192
         */
193
        @JsonProperty("provider")
194
        /* default */ String provider;
195
196
        /** Provider-specific model name. */
197
        @JsonProperty("model")
198
        /* default */ String model;
199
200
        /** Provider base URL override. */
201
        @JsonProperty("baseUrl")
202
        /* default */ String baseUrl;
203
204
        /** API key supplied directly. */
205
        @JsonProperty("apiKey")
206
        /* default */ String apiKey;
207
208
        /** Name of the environment variable that holds the API key. */
209
        @JsonProperty("apiKeyEnv")
210
        /* default */ String apiKeyEnv;
211
212
        /** Path to an external taxonomy file. */
213
        @JsonProperty("taxonomyFile")
214
        /* default */ String taxonomyFile;
215
216
        /** Built-in taxonomy variant: {@code default} or {@code optimized}. */
217
        @JsonProperty("taxonomyMode")
218
        /* default */ String taxonomyMode;
219
220
        /** Maximum number of characters of class source sent to the AI. */
221
        @JsonProperty("maxClassChars")
222
        /* default */ Integer maxClassChars;
223
224
        /** AI request timeout in seconds. */
225
        @JsonProperty("timeoutSec")
226
        /* default */ Long timeoutSec;
227
228
        /** Maximum number of retries for AI requests. */
229
        @JsonProperty("maxRetries")
230
        /* default */ Integer maxRetries;
231
232
        /** Whether to request a confidence score for each classification. */
233
        @JsonProperty("confidence")
234
        /* default */ Boolean confidence;
235
236
        /**
237
         * Azure OpenAI REST API version appended as the {@code api-version} query
238
         * parameter; only used when {@code provider: azure_openai} is set.
239
         */
240
        @JsonProperty("apiVersion")
241
        /* default */ String apiVersion;
242
    }
243
}

Mutations

86

1.1
Location : load
Killed by : org.egothor.methodatlas.YamlConfigTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.YamlConfigTest]/[method:load_parsesEmitMetadata(java.nio.file.Path)]
replaced return value with null for org/egothor/methodatlas/YamlConfig::load → KILLED

Active mutators

Tests examined


Report generated by PIT 1.22.1