Skip to content

Commit d3fd7ec

Browse files
SONARJAVA-6205 Add test script to generate profile from CSV file
1 parent 31312fc commit d3fd7ec

3 files changed

Lines changed: 101 additions & 0 deletions

File tree

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,11 @@
280280
<artifactId>commons-lang3</artifactId>
281281
<version>3.20.0</version>
282282
</dependency>
283+
<dependency>
284+
<groupId>org.apache.commons</groupId>
285+
<artifactId>commons-csv</artifactId>
286+
<version>1.14.1</version>
287+
</dependency>
283288
<dependency>
284289
<groupId>org.springframework</groupId>
285290
<artifactId>spring-expression</artifactId>

sonar-java-plugin/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,11 @@
137137
<version>${project.version}</version>
138138
<scope>test</scope>
139139
</dependency>
140+
<dependency>
141+
<groupId>org.apache.commons</groupId>
142+
<artifactId>commons-csv</artifactId>
143+
<scope>test</scope>
144+
</dependency>
140145
</dependencies>
141146

142147
<build>

sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaAgenticWayProfileTest.java

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,28 @@
1717
package org.sonar.plugins.java;
1818

1919

20+
import java.io.BufferedWriter;
21+
import java.io.FileReader;
22+
import java.io.FileWriter;
23+
import java.io.IOException;
24+
import java.nio.charset.StandardCharsets;
25+
import java.nio.file.Files;
26+
import java.nio.file.Path;
2027
import java.util.List;
2128
import java.util.Map;
29+
import java.util.Set;
30+
import java.util.stream.Collectors;
31+
import org.apache.commons.csv.CSVFormat;
32+
import org.junit.jupiter.api.Disabled;
2233
import org.junit.jupiter.api.Test;
2334
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
2435

2536
import static org.assertj.core.api.Assertions.assertThat;
2637

2738
class JavaAgenticWayProfileTest {
2839

40+
private static final Path RULE_DESCRIPTION_DIRECTORY = Path.of("sonar-java-plugin", "src", "main", "resources", "org", "sonar", "l10n", "java", "rules", "java");
41+
2942
@Test
3043
void profile_is_registered_as_expected() {
3144
JavaAgenticWayProfile profile = new JavaAgenticWayProfile();
@@ -104,4 +117,82 @@ void profile_is_registered_as_expected() {
104117
"S8491"
105118
));
106119
}
120+
121+
@Disabled("This method should be used as a utility method to generate a quality profile from a CSV file")
122+
void generate_ai_quality_profile() throws IOException {
123+
generate(
124+
Path.of("Path", "to", "your", "input.csv"),
125+
RULE_DESCRIPTION_DIRECTORY.resolve("Agentic_way_profile.json"),
126+
"AI Quality Profile"
127+
);
128+
}
129+
130+
public static Path generate(Path input, Path output, String profileName) throws IOException {
131+
CSVFormat csvFormat = CSVFormat.DEFAULT.builder()
132+
.setHeader()
133+
.setSkipHeaderRecord(true)
134+
.get();
135+
136+
Set<String> keysOfImplementedRules = getImplementedRuleKeys();
137+
138+
String ruleKeys;
139+
try (FileReader in = new FileReader(input.toFile(), StandardCharsets.UTF_8)) {
140+
ruleKeys = csvFormat.parse(in).stream()
141+
// Filter rules that have not been classified as AI and Sonar Way
142+
.filter(ruleRecord -> "AI and Sonar way".equalsIgnoreCase(ruleRecord.get("classification_status")))
143+
// Recover keys
144+
.map(ruleRecord -> ruleRecord.get("ruleid"))
145+
// Filter out keys that do not have a sonar-java implementation
146+
.filter(keysOfImplementedRules::contains)
147+
// Sort keys
148+
.sorted(JavaAgenticWayProfileTest::compareRuleKeys)
149+
// Surround with double quotes for output in JSON document
150+
.map(ruleKey -> " \"%s\"".formatted(ruleKey))
151+
// Comma and line separate rule keys
152+
.collect(Collectors.joining(",%s".formatted(System.lineSeparator())));
153+
}
154+
try (
155+
FileWriter out = new FileWriter(output.toFile(), StandardCharsets.UTF_8);
156+
BufferedWriter writer = new BufferedWriter(out)
157+
) {
158+
writer.write("{");
159+
writer.newLine();
160+
writer.write(" \"name\": \"%s\",".formatted(profileName));
161+
writer.newLine();
162+
writer.write(" \"ruleKeys\": [");
163+
writer.newLine();
164+
writer.write(ruleKeys);
165+
writer.newLine();
166+
writer.write(" ]");
167+
writer.newLine();
168+
writer.write("}");
169+
}
170+
return output;
171+
172+
}
173+
174+
private static Set<String> getImplementedRuleKeys() throws IOException {
175+
if (!Files.isDirectory(RULE_DESCRIPTION_DIRECTORY)) {
176+
throw new IllegalStateException("This should not happen!");
177+
}
178+
return Files.list(RULE_DESCRIPTION_DIRECTORY)
179+
.filter(path -> !path.endsWith("_profile.json"))
180+
.map(path -> {
181+
String fileName = path.getFileName().toString();
182+
return fileName.substring(0, fileName.lastIndexOf('.'));
183+
})
184+
.collect(Collectors.toSet());
185+
}
186+
187+
private static Integer getSortingKey(String ruleKey) {
188+
try {
189+
return Integer.parseInt(ruleKey.substring(1));
190+
} catch (NumberFormatException ignored) {
191+
return Integer.MIN_VALUE;
192+
}
193+
}
194+
195+
private static int compareRuleKeys(String first, String second) {
196+
return getSortingKey(first) - getSortingKey(second);
197+
}
107198
}

0 commit comments

Comments
 (0)