21
21
22
22
import java .util .UUID ;
23
23
import javax .annotation .CheckForNull ;
24
+ import org .eclipse .lsp4j .jsonrpc .ResponseErrorException ;
25
+ import org .eclipse .lsp4j .jsonrpc .messages .ResponseError ;
24
26
import org .sonarsource .sonarlint .core .SonarQubeClientManager ;
25
27
import org .sonarsource .sonarlint .core .branch .SonarProjectBranchTrackingService ;
26
28
import org .sonarsource .sonarlint .core .commons .log .SonarLintLogger ;
27
29
import org .sonarsource .sonarlint .core .commons .progress .SonarLintCancelMonitor ;
28
30
import org .sonarsource .sonarlint .core .repository .config .ConfigurationRepository ;
31
+ import org .sonarsource .sonarlint .core .rpc .protocol .SonarLintRpcErrorCode ;
29
32
import org .sonarsource .sonarlint .core .rpc .protocol .backend .sca .DependencyRiskTransition ;
33
+ import org .sonarsource .sonarlint .core .rpc .protocol .backend .tracking .AffectedPackageDto ;
34
+ import org .sonarsource .sonarlint .core .rpc .protocol .backend .sca .GetDependencyRiskDetailsResponse ;
35
+ import org .sonarsource .sonarlint .core .rpc .protocol .backend .tracking .ScaIssueDto ;
36
+ import org .sonarsource .sonarlint .core .serverapi .sca .GetIssueReleaseResponse ;
30
37
import org .sonarsource .sonarlint .core .serverconnection .issues .ServerScaIssue ;
31
38
import org .sonarsource .sonarlint .core .storage .StorageService ;
32
39
@@ -80,6 +87,23 @@ public void changeStatus(String configurationScopeId, UUID issueReleaseKey, Depe
80
87
serverConnection .withClientApi (serverApi -> serverApi .sca ().changeStatus (issueReleaseKey , transition .name (), comment , cancelMonitor ));
81
88
}
82
89
90
+ public GetDependencyRiskDetailsResponse getDependencyRiskDetails (String configurationScopeId , String dependencyRiskKey , SonarLintCancelMonitor cancelMonitor ) {
91
+ var configScope = configurationRepository .getConfigurationScope (configurationScopeId );
92
+ if (configScope == null ) {
93
+ var error = new ResponseError (SonarLintRpcErrorCode .CONFIG_SCOPE_NOT_FOUND , "The provided configuration scope does not exist: " + configurationScopeId , configurationScopeId );
94
+ throw new ResponseErrorException (error );
95
+ }
96
+ var effectiveBinding = configurationRepository .getEffectiveBinding (configurationScopeId );
97
+ if (effectiveBinding .isEmpty ()) {
98
+ var error = new ResponseError (SonarLintRpcErrorCode .CONFIG_SCOPE_NOT_BOUND ,
99
+ "The provided configuration scope is not bound to a SonarQube/SonarCloud project: " + configurationScopeId , configurationScopeId );
100
+ throw new ResponseErrorException (error );
101
+ }
102
+ var apiClient = sonarQubeClientManager .getClientOrThrow (effectiveBinding .get ().connectionId ());
103
+ var serverResponse = apiClient .withClientApiAndReturn (serverApi -> serverApi .sca ().getIssueRelease (dependencyRiskKey , cancelMonitor ));
104
+ return convertToRpcResponse (serverResponse );
105
+ }
106
+
83
107
private static ServerScaIssue .Transition adaptTransition (DependencyRiskTransition transition ) {
84
108
return switch (transition ) {
85
109
case REOPEN -> ServerScaIssue .Transition .REOPEN ;
@@ -90,6 +114,31 @@ private static ServerScaIssue.Transition adaptTransition(DependencyRiskTransitio
90
114
};
91
115
}
92
116
117
+ private static GetDependencyRiskDetailsResponse convertToRpcResponse (GetIssueReleaseResponse serverResponse ) {
118
+ var affectedPackages = serverResponse .affectedPackages ().stream ()
119
+ .map (pkg -> AffectedPackageDto .builder ()
120
+ .purl (pkg .purl ())
121
+ .recommendation (pkg .recommendation ())
122
+ .impactScore (pkg .recommendationDetails ().impactScore ())
123
+ .impactDescription (pkg .recommendationDetails ().impactDescription ())
124
+ .realIssue (pkg .recommendationDetails ().realIssue ())
125
+ .falsePositiveReason (pkg .recommendationDetails ().falsePositiveReason ())
126
+ .includesDev (pkg .recommendationDetails ().includesDev ())
127
+ .specificMethodsAffected (pkg .recommendationDetails ().specificMethodsAffected ())
128
+ .specificMethodsDescription (pkg .recommendationDetails ().specificMethodsDescription ())
129
+ .otherConditions (pkg .recommendationDetails ().otherConditions ())
130
+ .otherConditionsDescription (pkg .recommendationDetails ().otherConditionsDescription ())
131
+ .workaroundAvailable (pkg .recommendationDetails ().workaroundAvailable ())
132
+ .workaroundDescription (pkg .recommendationDetails ().workaroundDescription ())
133
+ .visibility (pkg .recommendationDetails ().visibility ())
134
+ .build ())
135
+ .toList ();
136
+
137
+ return new GetDependencyRiskDetailsResponse (serverResponse .key (), ScaIssueDto .Severity .valueOf (serverResponse .severity ().name ()), serverResponse .release ().packageName (),
138
+ serverResponse .release ().version (), ScaIssueDto .Type .valueOf (serverResponse .type ().name ()), serverResponse .vulnerability ().vulnerabilityId (),
139
+ serverResponse .vulnerability ().description (), affectedPackages );
140
+ }
141
+
93
142
public static class ScaIssueNotFoundException extends RuntimeException {
94
143
private final String issueKey ;
95
144
0 commit comments