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

Mutations

87

1.1
Location : load
Killed by : org.egothor.methodatlas.YamlConfigTest.[engine:junit-jupiter]/[class:org.egothor.methodatlas.YamlConfigTest]/[method:load_parsesMinConfidenceField(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