11package io .github .randomcodespace .sonarpredict .daemon ;
22
33import java .nio .file .Path ;
4+ import java .util .List ;
45
56import org .sonarsource .sonarlint .core .analysis .api .ClientInputFile ;
7+ import org .sonarsource .sonarlint .core .analysis .api .ClientInputFileEdit ;
68import org .sonarsource .sonarlint .core .analysis .api .Issue ;
79import org .sonarsource .sonarlint .core .commons .api .TextRange ;
810
11+ import io .github .randomcodespace .sonarpredict .protocol .dto .FileEdit ;
12+ import io .github .randomcodespace .sonarpredict .protocol .dto .QuickFix ;
913import io .github .randomcodespace .sonarpredict .protocol .dto .RuleMetadata ;
14+ import io .github .randomcodespace .sonarpredict .protocol .dto .TextEdit ;
1015
1116/**
1217 * Maps an engine {@link Issue} to the protocol {@link io.github.randomcodespace.sonarpredict.protocol.dto.Issue}.
@@ -45,18 +50,32 @@ public static io.github.randomcodespace.sonarpredict.protocol.dto.Issue toDto(
4550 resolveFilePath (engineIssue .getInputFile (), baseDir ),
4651 engineIssue .getTextRange (),
4752 engineIssue .getMessage (),
48- catalog );
53+ catalog ,
54+ mapQuickFixes (engineIssue .quickFixes (), baseDir ));
4955 }
5056
5157 /**
52- * Pure mapping from primitive issue fields to a protocol DTO. A {@code null}
53- * {@code range} (file-level issue) yields zero positions. Severity and type
54- * are resolved from {@code catalog} by {@code ruleKey}, falling back to
55- * {@link #DEFAULT_SEVERITY}/{@link #DEFAULT_TYPE} for unknown rules.
58+ * Pure mapping from primitive issue fields to a protocol DTO with no quick
59+ * fixes. A {@code null} {@code range} (file-level issue) yields zero
60+ * positions. Severity and type are resolved from {@code catalog} by
61+ * {@code ruleKey}, falling back to {@link #DEFAULT_SEVERITY}/{@link #DEFAULT_TYPE}
62+ * for unknown rules.
5663 */
5764 static io .github .randomcodespace .sonarpredict .protocol .dto .Issue map (
5865 String ruleKey , String filePath , TextRange range , String message ,
5966 RuleCatalog catalog ) {
67+ return map (ruleKey , filePath , range , message , catalog , List .of ());
68+ }
69+
70+ /**
71+ * Pure mapping from primitive issue fields to a protocol DTO with the
72+ * supplied {@code quickFixes}. Used by {@link #toDto} after extracting
73+ * the engine's quick fixes; tests can call this overload directly to
74+ * exercise the full DTO shape without spinning up the engine.
75+ */
76+ static io .github .randomcodespace .sonarpredict .protocol .dto .Issue map (
77+ String ruleKey , String filePath , TextRange range , String message ,
78+ RuleCatalog catalog , List <QuickFix > quickFixes ) {
6079 int startLine = range != null ? range .getStartLine () : 0 ;
6180 int startColumn = range != null ? range .getStartLineOffset () : 0 ;
6281 int endLine = range != null ? range .getEndLine () : 0 ;
@@ -79,7 +98,39 @@ static io.github.randomcodespace.sonarpredict.protocol.dto.Issue map(
7998 endColumn ,
8099 severity ,
81100 type ,
82- message );
101+ message ,
102+ quickFixes );
103+ }
104+
105+ /**
106+ * Maps the engine's {@link org.sonarsource.sonarlint.core.analysis.api.QuickFix}
107+ * list to the protocol's {@link QuickFix} DTOs.
108+ *
109+ * <p>Engine {@code QuickFix.message()} is preserved verbatim. Each
110+ * {@link ClientInputFileEdit}'s target is path-resolved the same way the
111+ * primary issue's input file is (via {@link #resolveFilePath}), so quick-fix
112+ * targets share the {@code baseDir}-relative, '/'-separated convention with
113+ * {@link io.github.randomcodespace.sonarpredict.protocol.dto.Issue#filePath}.
114+ */
115+ static List <QuickFix > mapQuickFixes (
116+ List <org .sonarsource .sonarlint .core .analysis .api .QuickFix > engineQuickFixes ,
117+ Path baseDir ) {
118+ return engineQuickFixes .stream ()
119+ .map (qf -> new QuickFix (
120+ qf .message (),
121+ qf .inputFileEdits ().stream ()
122+ .map (ife -> new FileEdit (
123+ resolveFilePath (ife .target (), baseDir ),
124+ ife .textEdits ().stream ()
125+ .map (te -> new TextEdit (
126+ te .range ().getStartLine (),
127+ te .range ().getStartLineOffset (),
128+ te .range ().getEndLine (),
129+ te .range ().getEndLineOffset (),
130+ te .newText ()))
131+ .toList ()))
132+ .toList ()))
133+ .toList ();
83134 }
84135
85136 private static String resolveFilePath (ClientInputFile inputFile , Path baseDir ) {
0 commit comments