1414 * You should have received a copy of the Sonar Source-Available License
1515 * along with this program; if not, see https://sonarsource.com/license/ssal/
1616 */
17- import type { analyzer } from '../proto/language_analyzer.js' ;
17+ import { analyzer } from '../proto/language_analyzer.js' ;
1818import type { ProjectAnalysisOutput } from '../../../jsts/src/analysis/projectAnalysis/projectAnalysis.js' ;
1919import type { Issue } from '../../../jsts/src/linter/issues/issue.js' ;
2020
@@ -41,7 +41,7 @@ const PARSING_ERROR_RULE_KEY = 'S2260';
4141 *
4242 * **Secondary Locations:**
4343 * Secondary locations provide additional context for issues (e.g., "this variable was declared here").
44- * They are grouped into a single flow in the gRPC format.
44+ * They are grouped into a single flow in the gRPC format with type FLOW_TYPE_DATA .
4545 *
4646 * @param issue - Internal Issue object from the linter
4747 * @returns gRPC IIssue object ready for protobuf serialization
@@ -57,7 +57,6 @@ function transformIssue(issue: Issue): analyzer.IIssue {
5757 // Transform secondary locations into flows
5858 const flows : analyzer . IFlow [ ] = [ ] ;
5959 if ( issue . secondaryLocations && issue . secondaryLocations . length > 0 ) {
60- // Group secondary locations into a single flow
6160 const locations : analyzer . IFlowLocation [ ] = issue . secondaryLocations . map ( loc => ( {
6261 textRange : {
6362 startLine : loc . line ,
@@ -69,7 +68,11 @@ function transformIssue(issue: Issue): analyzer.IIssue {
6968 file : issue . filePath ,
7069 } ) ) ;
7170
72- flows . push ( { locations } ) ;
71+ flows . push ( {
72+ type : analyzer . FlowType . FLOW_TYPE_DATA ,
73+ description : '' ,
74+ locations,
75+ } ) ;
7376 }
7477
7578 return {
@@ -83,7 +86,7 @@ function transformIssue(issue: Issue): analyzer.IIssue {
8386}
8487
8588/**
86- * Transform the ProjectAnalysisOutput into a gRPC AnalyzeFileResponse .
89+ * Transform the ProjectAnalysisOutput into a gRPC AnalyzeResponse .
8790 *
8891 * This is the main entry point for response transformation in the gRPC workflow.
8992 * It processes the analysis results for all files and converts them into the
@@ -94,41 +97,58 @@ function transformIssue(issue: Issue): analyzer.IIssue {
9497 * result can be one of three types:
9598 *
9699 * 1. **Error** (`'error' in result`): Analysis failed for this file
97- * - Added to `analysisProblems` array with file path context
100+ * - Added to `analysisProblems` array with UNDEFINED type
98101 *
99102 * 2. **Parsing Error** (`'parsingError' in result`): File could not be parsed
100- * - Converted to an issue with rule S2260 (parsing error rule)
101- * - Includes the error message and line number
103+ * - Added to `analysisProblems` array with PARSING type
104+ * - Also converted to an issue with rule S2260
102105 *
103106 * 3. **Success** (`'issues' in result`): Analysis completed successfully
104107 * - All issues are transformed and added to the response
105108 *
106109 * **Response Structure:**
107110 * ```
108- * IAnalyzeFileResponse
111+ * IAnalyzeResponse
109112 * ├── issues[] ──────────── All issues from successful analyses + parsing errors
110- * └── analysisProblems[] ── Warnings from meta + error messages for failed files
113+ * └── analysisProblems[] ── Structured problems with type, message, and file path
111114 * ```
112115 *
113116 * @param output - The ProjectAnalysisOutput from analyzeProject()
114- * @returns gRPC IAnalyzeFileResponse ready for protobuf serialization
117+ * @returns gRPC IAnalyzeResponse ready for protobuf serialization
115118 */
116119export function transformProjectOutputToResponse (
117120 output : ProjectAnalysisOutput ,
118- ) : analyzer . IAnalyzeFileResponse {
121+ ) : analyzer . IAnalyzeResponse {
119122 const issues : analyzer . IIssue [ ] = [ ] ;
120- const analysisProblems : string [ ] = [ ...output . meta . warnings ] ;
123+ const analysisProblems : analyzer . IAnalysisProblem [ ] = [ ] ;
124+
125+ for ( const warning of output . meta . warnings ) {
126+ analysisProblems . push ( {
127+ type : analyzer . AnalysisProblemType . ANALYSIS_PROBLEM_TYPE_UNDEFINED ,
128+ message : warning ,
129+ filePath : '' ,
130+ } ) ;
131+ }
121132
122- // Process each file result
123133 for ( const [ filePath , fileResult ] of Object . entries ( output . files ) ) {
124134 if ( 'error' in fileResult ) {
125- analysisProblems . push ( `Error analyzing ${ filePath } : ${ fileResult . error } ` ) ;
135+ analysisProblems . push ( {
136+ type : analyzer . AnalysisProblemType . ANALYSIS_PROBLEM_TYPE_UNDEFINED ,
137+ message : fileResult . error ,
138+ filePath,
139+ } ) ;
126140 continue ;
127141 }
128142
129143 if ( 'parsingError' in fileResult ) {
130- // Report parsing errors as issues with rule S2260
131144 const { message, line } = fileResult . parsingError ;
145+
146+ analysisProblems . push ( {
147+ type : analyzer . AnalysisProblemType . ANALYSIS_PROBLEM_TYPE_PARSING ,
148+ message,
149+ filePath,
150+ } ) ;
151+
132152 issues . push (
133153 transformIssue ( {
134154 ruleId : PARSING_ERROR_RULE_KEY ,
@@ -144,7 +164,6 @@ export function transformProjectOutputToResponse(
144164 continue ;
145165 }
146166
147- // Extract issues from successful analysis
148167 if ( 'issues' in fileResult ) {
149168 for ( const issue of fileResult . issues ) {
150169 issues . push ( transformIssue ( issue ) ) ;
0 commit comments