Skip to content

Commit 7c3ac3a

Browse files
Notify client when embedded server starts
1 parent 658a39b commit 7c3ac3a

File tree

9 files changed

+211
-27
lines changed

9 files changed

+211
-27
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
<properties>
2626
<jdk.min.version>17</jdk.min.version>
27-
<sonarlint.core.version>10.33.0.82369</sonarlint.core.version>
27+
<sonarlint.core.version>10.33.0.82428</sonarlint.core.version>
2828
<slf4j.version>2.0.17</slf4j.version>
2929
<!-- Version used by Xodus -->
3030
<kotlin.version>1.6.10</kotlin.version>

src/main/java/org/sonarsource/sonarlint/ls/SonarLintExtendedLanguageClient.java

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.sonarsource.sonarlint.core.rpc.protocol.client.binding.AssistBindingParams;
4141
import org.sonarsource.sonarlint.core.rpc.protocol.client.binding.SuggestBindingParams;
4242
import org.sonarsource.sonarlint.core.rpc.protocol.client.connection.SuggestConnectionParams;
43+
import org.sonarsource.sonarlint.core.rpc.protocol.client.embeddedserver.EmbeddedServerStartedParams;
4344
import org.sonarsource.sonarlint.core.rpc.protocol.client.fix.ChangesDto;
4445
import org.sonarsource.sonarlint.core.rpc.protocol.common.Either;
4546
import org.sonarsource.sonarlint.core.rpc.protocol.common.SonarCloudRegion;
@@ -340,13 +341,11 @@ public String getName() {
340341
}
341342

342343
public String getType() {
343-
return severityDetails.isLeft() ?
344-
severityDetails.getLeft().getType() : null;
344+
return severityDetails.isLeft() ? severityDetails.getLeft().getType() : null;
345345
}
346346

347347
public String getSeverity() {
348-
return severityDetails.isLeft() ?
349-
severityDetails.getLeft().getSeverity() : null;
348+
return severityDetails.isLeft() ? severityDetails.getLeft().getSeverity() : null;
350349
}
351350

352351
public boolean isTaint() {
@@ -366,13 +365,11 @@ public RuleDescriptionTab[] getHtmlDescriptionTabs() {
366365
}
367366

368367
public String getCleanCodeAttribute() {
369-
return severityDetails.isRight() ?
370-
severityDetails.getRight().getCleanCodeAttribute() : null;
368+
return severityDetails.isRight() ? severityDetails.getRight().getCleanCodeAttribute() : null;
371369
}
372370

373371
public String getCleanCodeAttributeCategory() {
374-
return severityDetails.isRight() ?
375-
severityDetails.getRight().getCleanCodeAttributeCategory() : null;
372+
return severityDetails.isRight() ? severityDetails.getRight().getCleanCodeAttributeCategory() : null;
376373
}
377374

378375
public Map<String, String> getImpacts() {
@@ -381,8 +378,12 @@ public Map<String, String> getImpacts() {
381378

382379
@Override
383380
public boolean equals(Object o) {
384-
if (this == o) return true;
385-
if (o == null || getClass() != o.getClass()) return false;
381+
if (this == o) {
382+
return true;
383+
}
384+
if (o == null || getClass() != o.getClass()) {
385+
return false;
386+
}
386387
ShowRuleDescriptionParams that = (ShowRuleDescriptionParams) o;
387388
return isTaint == that.isTaint
388389
&& Objects.equals(key, that.key)
@@ -431,16 +432,20 @@ public RuleDescriptionTab(String title, RuleDescriptionTabContextual[] ruleDescr
431432

432433
public RuleDescriptionTab(String title, RuleDescriptionTabNonContextual ruleDescriptionTabNonContextual) {
433434
this.title = title;
434-
this.ruleDescriptionTabContextual = new RuleDescriptionTabContextual[]{};
435+
this.ruleDescriptionTabContextual = new RuleDescriptionTabContextual[] {};
435436
this.ruleDescriptionTabNonContextual = ruleDescriptionTabNonContextual;
436437
this.hasContextualInformation = false;
437438
this.defaultContextKey = "";
438439
}
439440

440441
@Override
441442
public boolean equals(Object o) {
442-
if (this == o) return true;
443-
if (o == null || getClass() != o.getClass()) return false;
443+
if (this == o) {
444+
return true;
445+
}
446+
if (o == null || getClass() != o.getClass()) {
447+
return false;
448+
}
444449
RuleDescriptionTab that = (RuleDescriptionTab) o;
445450
return hasContextualInformation == that.hasContextualInformation
446451
&& Objects.equals(title, that.title)
@@ -505,8 +510,12 @@ public String getDisplayName() {
505510

506511
@Override
507512
public boolean equals(Object o) {
508-
if (this == o) return true;
509-
if (o == null || getClass() != o.getClass()) return false;
513+
if (this == o) {
514+
return true;
515+
}
516+
if (o == null || getClass() != o.getClass()) {
517+
return false;
518+
}
510519
RuleDescriptionTabContextual that = (RuleDescriptionTabContextual) o;
511520
return Objects.equals(htmlContent, that.htmlContent) && Objects.equals(contextKey, that.contextKey) && Objects.equals(displayName,
512521
that.displayName);
@@ -532,8 +541,12 @@ public String getHtmlContent() {
532541

533542
@Override
534543
public boolean equals(Object o) {
535-
if (this == o) return true;
536-
if (o == null || getClass() != o.getClass()) return false;
544+
if (this == o) {
545+
return true;
546+
}
547+
if (o == null || getClass() != o.getClass()) {
548+
return false;
549+
}
537550
RuleDescriptionTabNonContextual that = (RuleDescriptionTabNonContextual) o;
538551
return Objects.equals(htmlContent, that.htmlContent);
539552
}
@@ -796,8 +809,8 @@ public String getReason() {
796809
CompletableFuture<Boolean> isOpenInEditor(String fileUri);
797810

798811
record SslCertificateConfirmationParams(@Expose String issuedTo, @Expose String issuedBy, @Expose String validFrom,
799-
@Expose String validTo, @Expose String sha1Fingerprint,
800-
@Expose String sha256Fingerprint) {
812+
@Expose String validTo, @Expose String sha1Fingerprint,
813+
@Expose String sha256Fingerprint) {
801814
}
802815

803816
@JsonRequest("askSslCertificateConfirmation")
@@ -865,8 +878,12 @@ public String getFolderUri() {
865878

866879
@Override
867880
public boolean equals(Object o) {
868-
if (this == o) return true;
869-
if (o == null || getClass() != o.getClass()) return false;
881+
if (this == o) {
882+
return true;
883+
}
884+
if (o == null || getClass() != o.getClass()) {
885+
return false;
886+
}
870887
FolderUriParams that = (FolderUriParams) o;
871888
return Objects.equals(folderUri, that.folderUri);
872889
}
@@ -886,8 +903,12 @@ record NotifyInvalidTokenParams(String connectionId) {
886903
@JsonNotification("notifyInvalidToken")
887904
void notifyInvalidToken(NotifyInvalidTokenParams params);
888905

889-
record FlightRecorderStartedParams(String sessionId) {}
906+
record FlightRecorderStartedParams(String sessionId) {
907+
}
890908

891909
@JsonNotification("flightRecorderStarted")
892910
void flightRecorderStarted(FlightRecorderStartedParams params);
911+
912+
@JsonNotification("embeddedServerStarted")
913+
void embeddedServerStarted(EmbeddedServerStartedParams params);
893914
}

src/main/java/org/sonarsource/sonarlint/ls/SonarLintLanguageServer.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
import org.sonarsource.sonarlint.ls.file.FileTypeClassifier;
121121
import org.sonarsource.sonarlint.ls.file.OpenFilesCache;
122122
import org.sonarsource.sonarlint.ls.file.VersionedOpenFile;
123+
import org.sonarsource.sonarlint.ls.embeddedserver.EmbeddedServerManager;
123124
import org.sonarsource.sonarlint.ls.flightrecorder.FlightRecorderManager;
124125
import org.sonarsource.sonarlint.ls.folders.ModuleEventsProcessor;
125126
import org.sonarsource.sonarlint.ls.folders.WorkspaceFolderBranchManager;
@@ -160,6 +161,7 @@ public class SonarLintLanguageServer implements SonarLintExtendedLanguageServer,
160161
public static final String PYTHON_LANGUAGE = "python";
161162
private final SonarLintExtendedLanguageClient client;
162163
private final FlightRecorderManager flightRecorderManager;
164+
private final EmbeddedServerManager embeddedServerManager;
163165
private final SonarLintTelemetry telemetry;
164166
private final WorkspaceFoldersManager workspaceFoldersManager;
165167
private final SettingsManager settingsManager;
@@ -210,6 +212,7 @@ public class SonarLintLanguageServer implements SonarLintExtendedLanguageServer,
210212
this.openFilesCache = new OpenFilesCache(lsLogOutput);
211213

212214
this.flightRecorderManager = new FlightRecorderManager(client);
215+
this.embeddedServerManager = new EmbeddedServerManager(client);
213216
this.issuesCache = new IssuesCache();
214217
this.securityHotspotsCache = new HotspotsCache();
215218
var taintVulnerabilitiesCache = new TaintVulnerabilitiesCache();
@@ -221,7 +224,7 @@ public class SonarLintLanguageServer implements SonarLintExtendedLanguageServer,
221224
var skippedPluginsNotifier = new SkippedPluginsNotifier(client, lsLogOutput);
222225
var promotionalNotifications = new PromotionalNotifications(client);
223226
vsCodeClient = new SonarLintVSCodeClient(client, hostInfoProvider, lsLogOutput, taintVulnerabilitiesCache, dependencyRisksCache, skippedPluginsNotifier,
224-
promotionalNotifications, flightRecorderManager);
227+
promotionalNotifications, flightRecorderManager, embeddedServerManager);
225228
this.backendServiceFacade = new BackendServiceFacade(vsCodeClient, lsLogOutput, client, new EnabledLanguages(analyzers, lsLogOutput));
226229
vsCodeClient.setBackendServiceFacade(backendServiceFacade);
227230
this.workspaceFoldersManager = new WorkspaceFoldersManager(backendServiceFacade, lsLogOutput);
@@ -330,6 +333,7 @@ public void initialized(InitializedParams params) {
330333
lsLogOutput.debug("Language Server initialized");
331334
settingsManager.didChangeConfiguration();
332335
flightRecorderManager.initialized();
336+
embeddedServerManager.initialized();
333337
return null;
334338
});
335339
}

src/main/java/org/sonarsource/sonarlint/ls/clientapi/SonarLintVSCodeClient.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import org.sonarsource.sonarlint.core.rpc.protocol.client.connection.AssistCreatingConnectionResponse;
7171
import org.sonarsource.sonarlint.core.rpc.protocol.client.connection.ConnectionSuggestionDto;
7272
import org.sonarsource.sonarlint.core.rpc.protocol.client.connection.SuggestConnectionParams;
73+
import org.sonarsource.sonarlint.core.rpc.protocol.client.embeddedserver.EmbeddedServerStartedParams;
7374
import org.sonarsource.sonarlint.core.rpc.protocol.client.fix.FixSuggestionDto;
7475
import org.sonarsource.sonarlint.core.rpc.protocol.client.flightrecorder.FlightRecorderStartedParams;
7576
import org.sonarsource.sonarlint.core.rpc.protocol.client.hotspot.HotspotDetailsDto;
@@ -107,6 +108,7 @@
107108
import org.sonarsource.sonarlint.ls.connected.notifications.SmartNotifications;
108109
import org.sonarsource.sonarlint.ls.domain.DependencyRisk;
109110
import org.sonarsource.sonarlint.ls.domain.TaintIssue;
111+
import org.sonarsource.sonarlint.ls.embeddedserver.EmbeddedServerManager;
110112
import org.sonarsource.sonarlint.ls.flightrecorder.FlightRecorderManager;
111113
import org.sonarsource.sonarlint.ls.folders.WorkspaceFolderBranchManager;
112114
import org.sonarsource.sonarlint.ls.folders.WorkspaceFolderWrapper;
@@ -143,13 +145,14 @@ public class SonarLintVSCodeClient implements SonarLintRpcClientDelegate {
143145
private final SkippedPluginsNotifier skippedPluginsNotifier;
144146
private final PromotionalNotifications promotionalNotifications;
145147
private final FlightRecorderManager flightRecorderManager;
148+
private final EmbeddedServerManager embeddedServerManager;
146149
private final LSProgressMonitor progressMonitor;
147150

148151
private AnalysisHelper analysisHelper;
149152

150153
public SonarLintVSCodeClient(SonarLintExtendedLanguageClient client, HostInfoProvider hostInfoProvider, LanguageClientLogger logOutput,
151154
TaintVulnerabilitiesCache taintVulnerabilitiesCache, DependencyRisksCache dependencyRisksCache, SkippedPluginsNotifier skippedPluginsNotifier,
152-
PromotionalNotifications promotionalNotifications, FlightRecorderManager flightRecorderManager) {
155+
PromotionalNotifications promotionalNotifications, FlightRecorderManager flightRecorderManager, EmbeddedServerManager embeddedServerManager) {
153156
this.client = client;
154157
this.hostInfoProvider = hostInfoProvider;
155158
this.logOutput = logOutput;
@@ -158,6 +161,7 @@ public SonarLintVSCodeClient(SonarLintExtendedLanguageClient client, HostInfoPro
158161
this.skippedPluginsNotifier = skippedPluginsNotifier;
159162
this.promotionalNotifications = promotionalNotifications;
160163
this.flightRecorderManager = flightRecorderManager;
164+
this.embeddedServerManager = embeddedServerManager;
161165
this.progressMonitor = new LSProgressMonitor(client);
162166
var bindingSuggestionsThreadFactory = Utils.threadFactory("Binding suggestion handler", false);
163167
bindingSuggestionsHandler = Executors.newSingleThreadScheduledExecutor(bindingSuggestionsThreadFactory);
@@ -687,4 +691,9 @@ public void invalidToken(String connectionId) {
687691
public void flightRecorderStarted(FlightRecorderStartedParams params) {
688692
flightRecorderManager.onFlightRecorderStarted(params.getSessionId());
689693
}
694+
695+
@Override
696+
public void embeddedServerStarted(EmbeddedServerStartedParams params) {
697+
embeddedServerManager.embeddedServerStarted(params.getPort());
698+
}
690699
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* SonarLint Language Server
3+
* Copyright (C) 2009-2025 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonarsource.sonarlint.ls.embeddedserver;
21+
22+
import org.sonarsource.sonarlint.core.rpc.protocol.client.embeddedserver.EmbeddedServerStartedParams;
23+
import org.sonarsource.sonarlint.ls.SonarLintExtendedLanguageClient;
24+
25+
public class EmbeddedServerManager {
26+
27+
private final SonarLintExtendedLanguageClient client;
28+
29+
private boolean initialized;
30+
private Integer port;
31+
32+
public EmbeddedServerManager(SonarLintExtendedLanguageClient client) {
33+
this.client = client;
34+
}
35+
36+
public void embeddedServerStarted(int port) {
37+
this.port = port;
38+
if (initialized) {
39+
sendEmbeddedServerStartedToClient();
40+
}
41+
}
42+
43+
public void initialized() {
44+
this.initialized = true;
45+
if (port != null) {
46+
sendEmbeddedServerStartedToClient();
47+
}
48+
}
49+
50+
private void sendEmbeddedServerStartedToClient() {
51+
client.embeddedServerStarted(new EmbeddedServerStartedParams(port));
52+
}
53+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* SonarLint Language Server
3+
* Copyright (C) 2009-2025 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
@ParametersAreNonnullByDefault
21+
package org.sonarsource.sonarlint.ls.embeddedserver;
22+
23+
import javax.annotation.ParametersAreNonnullByDefault;

src/test/java/org/sonarsource/sonarlint/ls/clientapi/SonarLintVSCodeClientTests.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
import org.sonarsource.sonarlint.ls.connected.notifications.SmartNotifications;
119119
import org.sonarsource.sonarlint.ls.domain.DependencyRisk;
120120
import org.sonarsource.sonarlint.ls.domain.TaintIssue;
121+
import org.sonarsource.sonarlint.ls.embeddedserver.EmbeddedServerManager;
121122
import org.sonarsource.sonarlint.ls.flightrecorder.FlightRecorderManager;
122123
import org.sonarsource.sonarlint.ls.folders.WorkspaceFolderBranchManager;
123124
import org.sonarsource.sonarlint.ls.folders.WorkspaceFolderWrapper;
@@ -176,6 +177,7 @@ class SonarLintVSCodeClientTests {
176177
DiagnosticPublisher diagnosticPublisher = mock(DiagnosticPublisher.class);
177178
PromotionalNotifications promotionalNotifications = mock(PromotionalNotifications.class);
178179
FlightRecorderManager flightRecorderManager = mock(FlightRecorderManager.class);
180+
EmbeddedServerManager embeddedServerManager = mock(EmbeddedServerManager.class);
179181

180182
AnalysisHelper analysisHelper = mock(AnalysisHelper.class);
181183
WorkspaceFolderBranchManager branchManager = mock(WorkspaceFolderBranchManager.class);
@@ -219,7 +221,8 @@ class SonarLintVSCodeClientTests {
219221

220222
@BeforeEach
221223
void setup() throws IOException {
222-
underTest = new SonarLintVSCodeClient(client, server, logTester.getLogger(), taintVulnerabilitiesCache, dependencyRisksCache, skippedPluginsNotifier, promotionalNotifications, flightRecorderManager);
224+
underTest = new SonarLintVSCodeClient(client, server, logTester.getLogger(), taintVulnerabilitiesCache, dependencyRisksCache, skippedPluginsNotifier, promotionalNotifications,
225+
flightRecorderManager, embeddedServerManager);
223226
underTest.setSmartNotifications(smartNotifications);
224227
underTest.setSettingsManager(settingsManager);
225228
underTest.setBindingManager(bindingManager);

0 commit comments

Comments
 (0)