Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

moved initializeParams to serverOptions class #185

Merged
merged 7 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions src/main/java/software/amazon/smithy/lsp/ServerOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.lsp;

import com.google.gson.JsonObject;
import java.util.Arrays;
import java.util.Optional;
import org.eclipse.lsp4j.InitializeParams;
import software.amazon.smithy.model.validation.Severity;

public final class ServerOptions {
private final Severity minimumSeverity;
private final boolean onlyReloadOnSave;

private ServerOptions(Builder builder) {
this.minimumSeverity = builder.minimumSeverity;
this.onlyReloadOnSave = builder.onlyReloadOnSave;
}

public Severity getMinimumSeverity() {
return this.minimumSeverity;
}

public boolean getOnlyReloadOnSave() {
return this.onlyReloadOnSave;
}

public static Builder builder() {
return new Builder();
}

/**
* Creates a ServerOptions instance from the initialization options provided by the client.
* Parses and validates configuration settings from the initialization parameters.
*
* @param params The params passed directly from the client,
* expected to be an InitializeParams object containing server configurations
* @param client The language client used for logging configuration status and errors
* @return A new {@code ServerOptions} instance with parsed configuration values
**/
public static ServerOptions fromInitializeParams(InitializeParams params, SmithyLanguageClient client) {
// from InitializeParams
Object initializationOptions = params.getInitializationOptions();
Builder builder = builder();
if (initializationOptions instanceof JsonObject jsonObject) {
if (jsonObject.has("diagnostics.minimumSeverity")) {
String configuredMinimumSeverity = jsonObject.get("diagnostics.minimumSeverity").getAsString();
Optional<Severity> severity = Severity.fromString(configuredMinimumSeverity);
if (severity.isPresent()) {
builder.setMinimumSeverity(severity.get());
} else {
client.error(String.format("""
Invalid value for 'diagnostics.minimumSeverity': %s.
Must be one of %s.""", configuredMinimumSeverity, Arrays.toString(Severity.values())));
}
}
if (jsonObject.has("onlyReloadOnSave")) {
builder.setOnlyReloadOnSave(jsonObject.get("onlyReloadOnSave").getAsBoolean());
client.info("Configured only reload on save: " + builder.onlyReloadOnSave);
}
}
return builder.build();
}

protected static final class Builder {
private Severity minimumSeverity = Severity.WARNING;
private boolean onlyReloadOnSave = false;

public Builder setMinimumSeverity(Severity minimumSeverity) {
this.minimumSeverity = minimumSeverity;
return this;
}

public Builder setOnlyReloadOnSave(boolean onlyReloadOnSave) {
this.onlyReloadOnSave = onlyReloadOnSave;
return this;
}

public ServerOptions build() {
return new ServerOptions(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@

import static java.util.concurrent.CompletableFuture.completedFuture;

import com.google.gson.JsonObject;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
Expand All @@ -45,6 +43,7 @@
import org.eclipse.lsp4j.CompletionParams;
import org.eclipse.lsp4j.DefinitionParams;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.DiagnosticSeverity;
import org.eclipse.lsp4j.DidChangeConfigurationParams;
import org.eclipse.lsp4j.DidChangeTextDocumentParams;
import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
Expand Down Expand Up @@ -145,9 +144,8 @@ public class SmithyLanguageServer implements

private SmithyLanguageClient client;
private final ServerState state = new ServerState();
private Severity minimumSeverity = Severity.WARNING;
private boolean onlyReloadOnSave = false;
private ClientCapabilities clientCapabilities;
private ServerOptions serverOptions;

SmithyLanguageServer() {
}
Expand All @@ -161,7 +159,7 @@ ServerState getState() {
}

Severity getMinimumSeverity() {
return minimumSeverity;
return this.serverOptions.getMinimumSeverity();
}

@Override
Expand All @@ -187,25 +185,8 @@ public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
.flatMap(ProcessHandle::of)
.ifPresent(processHandle -> processHandle.onExit().thenRun(this::exit));

this.serverOptions = ServerOptions.fromInitializeParams(params, client);
// TODO: Replace with a Gson Type Adapter if more config options are added beyond `logToFile`.
Object initializationOptions = params.getInitializationOptions();
if (initializationOptions instanceof JsonObject jsonObject) {
if (jsonObject.has("diagnostics.minimumSeverity")) {
String configuredMinimumSeverity = jsonObject.get("diagnostics.minimumSeverity").getAsString();
Optional<Severity> severity = Severity.fromString(configuredMinimumSeverity);
if (severity.isPresent()) {
this.minimumSeverity = severity.get();
} else {
client.error(String.format("""
Invalid value for 'diagnostics.minimumSeverity': %s.
Must be one of %s.""", configuredMinimumSeverity, Arrays.toString(Severity.values())));
}
}
if (jsonObject.has("onlyReloadOnSave")) {
this.onlyReloadOnSave = jsonObject.get("onlyReloadOnSave").getAsBoolean();
client.info("Configured only reload on save: " + this.onlyReloadOnSave);
}
}

if (params.getWorkspaceFolders() != null && !params.getWorkspaceFolders().isEmpty()) {
Either<String, Integer> workDoneProgressToken = params.getWorkDoneToken();
Expand Down Expand Up @@ -523,7 +504,7 @@ public void didChange(DidChangeTextDocumentParams params) {
}

smithyFile.reparse();
if (!onlyReloadOnSave) {
if (!this.serverOptions.getOnlyReloadOnSave()) {
Project project = projectAndFile.project();

// TODO: A consequence of this is that any existing validation events are cleared, which
Expand Down Expand Up @@ -692,7 +673,7 @@ public CompletableFuture<Hover> hover(HoverParams params) {
Project project = projectAndFile.project();

// TODO: Abstract away passing minimum severity
var handler = new HoverHandler(project, smithyFile, minimumSeverity);
var handler = new HoverHandler(project, smithyFile, this.serverOptions.getMinimumSeverity());
return CompletableFuture.supplyAsync(() -> handler.handle(params));
}

Expand Down Expand Up @@ -739,7 +720,7 @@ private void sendFileDiagnosticsForManagedDocuments() {

private CompletableFuture<Void> sendFileDiagnostics(ProjectAndFile projectAndFile) {
return CompletableFuture.runAsync(() -> {
List<Diagnostic> diagnostics = SmithyDiagnostics.getFileDiagnostics(projectAndFile, minimumSeverity);
List<Diagnostic> diagnostics = SmithyDiagnostics.getFileDiagnostics(projectAndFile, this.serverOptions.getMinimumSeverity());
var publishDiagnosticsParams = new PublishDiagnosticsParams(projectAndFile.uri(), diagnostics);
client.publishDiagnostics(publishDiagnosticsParams);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import org.eclipse.lsp4j.FileChangeType;
import org.eclipse.lsp4j.FormattingOptions;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.InitializeParams;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.PublishDiagnosticsParams;
Expand All @@ -72,6 +73,7 @@
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.traits.LengthTrait;
import software.amazon.smithy.model.validation.Severity;

public class SmithyLanguageServerTest {
@Test
Expand Down Expand Up @@ -1913,6 +1915,53 @@ public void reloadsProjectOnBuildFileSave() {
Map.of()));
}

@Test
public void testCustomServerOptions() {
ServerOptions options = ServerOptions.builder()
.setMinimumSeverity(Severity.NOTE)
.setOnlyReloadOnSave(true)
.build();

assertThat(options.getMinimumSeverity(), equalTo(Severity.NOTE));
assertThat(options.getOnlyReloadOnSave(), equalTo(true));
}

@Test
public void testFromInitializeParamsWithValidOptions() {
StubClient client = new StubClient();
// Create initialization options
JsonObject opts = new JsonObject();
opts.add("diagnostics.minimumSeverity", new JsonPrimitive("ERROR"));
opts.add("onlyReloadOnSave", new JsonPrimitive(true));

// Create InitializeParams with the options
InitializeParams params = new InitializeParams();
params.setInitializationOptions(opts);

// Call the method being tested
ServerOptions options = ServerOptions.fromInitializeParams(params, new SmithyLanguageClient(client));

assertThat(options.getMinimumSeverity(), equalTo(Severity.ERROR));
assertThat(options.getOnlyReloadOnSave(), equalTo(true));
}

@Test
public void testFromInitializeParamsWithPartialOptions() {
StubClient client = new StubClient();
JsonObject opts = new JsonObject();
opts.add("onlyReloadOnSave", new JsonPrimitive(true));
// Not setting minimumSeverity

// Create InitializeParams with the options
InitializeParams params = new InitializeParams();
params.setInitializationOptions(opts);

ServerOptions options = ServerOptions.fromInitializeParams(params, new SmithyLanguageClient(client));

assertThat(options.getMinimumSeverity(), equalTo(Severity.WARNING)); // Default value
assertThat(options.getOnlyReloadOnSave(), equalTo(true)); // Explicitly set value
}

private void assertServerState(SmithyLanguageServer server, ServerState expected) {
ServerState actual = ServerState.from(server);
assertThat(actual, equalTo(expected));
Expand Down
Loading