-
Notifications
You must be signed in to change notification settings - Fork 27
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
feat: Add client-side language server configuration with per-language case sensitivity as the first available option (issue 626) #659
Changes from all commits
954164d
cbb923f
8a3e1de
e898618
500d7fd
bc4d8ef
696165d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -162,7 +162,8 @@ private void loadServersAndMappingFromSettings() { | |
launch.getUserEnvironmentVariables(), | ||
launch.isIncludeSystemEnvironmentVariables(), | ||
launch.getConfigurationContent(), | ||
launch.getInitializationOptionsContent()), | ||
launch.getInitializationOptionsContent(), | ||
launch.getClientConfigurationContent()), | ||
mappings); | ||
} | ||
} catch (Exception e) { | ||
|
@@ -365,6 +366,7 @@ private void addServerDefinitionWithoutNotification(@NotNull LanguageServerDefin | |
} | ||
settings.setConfigurationContent(definitionFromSettings.getConfigurationContent()); | ||
settings.setInitializationOptionsContent(definitionFromSettings.getInitializationOptionsContent()); | ||
settings.setClientConfigurationContent(definitionFromSettings.getClientConfigurationContent()); | ||
UserDefinedLanguageServerSettings.getInstance().setLaunchConfigSettings(languageServerId, settings); | ||
} | ||
} | ||
|
@@ -469,6 +471,7 @@ private void removeAssociationsFor(LanguageServerDefinition definition) { | |
request.serverDefinition().setIncludeSystemEnvironmentVariables(request.includeSystemEnvironmentVariables()); | ||
request.serverDefinition().setConfigurationContent(request.configurationContent()); | ||
request.serverDefinition().setInitializationOptionsContent(request.initializationOptionsContent()); | ||
request.serverDefinition().setClientConfigurationContent(request.clientConfigurationContent()); | ||
|
||
// remove associations | ||
removeAssociationsFor(request.serverDefinition()); | ||
|
@@ -483,13 +486,15 @@ private void removeAssociationsFor(LanguageServerDefinition definition) { | |
boolean mappingsChanged = !Objects.deepEquals(settings.getMappings(), request.mappings()); | ||
boolean configurationContentChanged = !Objects.equals(settings.getConfigurationContent(), request.configurationContent()); | ||
boolean initializationOptionsContentChanged = !Objects.equals(settings.getInitializationOptionsContent(), request.initializationOptionsContent()); | ||
// Not checking whether client config changed because that shouldn't result in a LanguageServerChangedEvent | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Specifically calling out that we don't need to include client config changes when computing whether or not to send an event here because the actual language server doesn't care at all about client-side config changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the moment I agree with you. Lets keep like this, but we could have a client settings which could impact the editor (like enable/disable lsp codelens which should refresh the editor and in this case we should send an event) |
||
|
||
settings.setServerName(request.name()); | ||
settings.setCommandLine(request.commandLine()); | ||
settings.setUserEnvironmentVariables(request.userEnvironmentVariables()); | ||
settings.setIncludeSystemEnvironmentVariables(request.includeSystemEnvironmentVariables()); | ||
settings.setConfigurationContent(request.configurationContent()); | ||
settings.setInitializationOptionsContent(request.initializationOptionsContent()); | ||
settings.setClientConfigurationContent(request.clientConfigurationContent); | ||
settings.setMappings(request.mappings()); | ||
|
||
if (nameChanged || commandChanged || userEnvironmentVariablesChanged || includeSystemEnvironmentVariablesChanged || | ||
|
@@ -578,7 +583,8 @@ public record UpdateServerDefinitionRequest(@NotNull Project project, | |
boolean includeSystemEnvironmentVariables, | ||
@NotNull List<ServerMappingSettings> mappings, | ||
@Nullable String configurationContent, | ||
@Nullable String initializationOptionsContent) { | ||
@Nullable String initializationOptionsContent, | ||
@Nullable String clientConfigurationContent) { | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -215,32 +215,47 @@ public boolean isItemTextBold(@NotNull CompletionItem item) { | |
/** | ||
* Don't override this method, we need to revisit the API and the prefix computation (to customize it). | ||
* | ||
* @param context | ||
* @param completionPrefix | ||
* @param result | ||
* @param lookupItem | ||
* @param priority | ||
* @param item | ||
*/ | ||
@ApiStatus.Internal | ||
public void addLookupItem(@NotNull CompletionPrefix completionPrefix, | ||
public void addLookupItem(@NotNull LSPCompletionContext context, | ||
@NotNull CompletionPrefix completionPrefix, | ||
@NotNull CompletionResultSet result, | ||
@NotNull LookupElement lookupItem, | ||
int priority, | ||
@NotNull CompletionItem item) { | ||
// Determine whether or not completions should be case-sensitive | ||
boolean caseSensitive = isCaseSensitive(context.getParameters().getOriginalFile()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that both |
||
|
||
var prioritizedLookupItem = PrioritizedLookupElement.withPriority(lookupItem, priority); | ||
|
||
// Compute the prefix | ||
var textEditRange = ((LSPCompletionProposal) lookupItem).getTextEditRange(); | ||
String prefix = textEditRange != null ? completionPrefix.getPrefixFor(textEditRange, item) : null; | ||
if (prefix != null) { | ||
// Add the IJ completion item (lookup item) by using the computed prefix | ||
result.withPrefixMatcher(prefix) | ||
.caseInsensitive() | ||
.addElement(prioritizedLookupItem); | ||
// Add the IJ completion item (lookup item) by using the computed prefix respecting the language's case-sensitivity | ||
if (caseSensitive) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could condense these two conditionals slightly be extracting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need to revisit this addLookupItem method so please dont loose your time about it |
||
result.withPrefixMatcher(prefix) | ||
.addElement(prioritizedLookupItem); | ||
} else { | ||
result.withPrefixMatcher(prefix) | ||
.caseInsensitive() | ||
.addElement(prioritizedLookupItem); | ||
} | ||
} else { | ||
// Should happen rarely, only when text edit is for multi-lines or if completion is triggered outside the text edit range. | ||
// Add the IJ completion item (lookup item) which will use the IJ prefix | ||
result.caseInsensitive() | ||
.addElement(prioritizedLookupItem); | ||
// Add the IJ completion item (lookup item) which will use the IJ prefix respecting the language's case-sensitivity | ||
if (caseSensitive) { | ||
result.addElement(prioritizedLookupItem); | ||
} else { | ||
result.caseInsensitive() | ||
.addElement(prioritizedLookupItem); | ||
} | ||
} | ||
} | ||
|
||
|
@@ -278,4 +293,15 @@ public void setServerCapabilities(@Nullable ServerCapabilities serverCapabilitie | |
completionCapabilityRegistry.setServerCapabilities(serverCapabilities); | ||
} | ||
} | ||
|
||
/** | ||
* Determines whether or not completions for the file should be offered in a case-sensitive manner. | ||
* | ||
* @param file the file | ||
* @return true if completions should be offered in a case-sensitive manner; otherwise false | ||
*/ | ||
public boolean isCaseSensitive(@NotNull PsiFile file) { | ||
// Default to case-insensitive | ||
return false; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -119,6 +119,8 @@ public static class UserDefinedLanguageServerItemSettings { | |
|
||
private String initializationOptionsContent; | ||
|
||
private String clientConfigurationContent = "{}"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The default value of |
||
|
||
@XCollection(elementTypes = ServerMappingSettings.class) | ||
private List<ServerMappingSettings> mappings; | ||
|
||
|
@@ -206,6 +208,14 @@ public String getInitializationOptionsContent() { | |
public void setInitializationOptionsContent(String initializationOptionsContent) { | ||
this.initializationOptionsContent = initializationOptionsContent; | ||
} | ||
|
||
public String getClientConfigurationContent() { | ||
return clientConfigurationContent; | ||
} | ||
|
||
public void setClientConfigurationContent(String clientConfigurationContent) { | ||
this.clientConfigurationContent = clientConfigurationContent; | ||
} | ||
} | ||
|
||
public static class MyState { | ||
|
@@ -215,7 +225,5 @@ public static class MyState { | |
|
||
MyState() { | ||
} | ||
|
||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,7 @@ public String getName() { | |
public static final String TEMPLATE_FILE_NAME = "template.json"; | ||
public static final String INITIALIZATION_OPTIONS_FILE_NAME = "initializationOptions.json"; | ||
public static final String SETTINGS_FILE_NAME = "settings.json"; | ||
public static final String CLIENT_SETTINGS_FILE_NAME = "clientSettings.json"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Following the existing pattern of the server-side config file being named |
||
public static final String README_FILE_NAME = "README.md"; | ||
|
||
public static final String LANGUAGE_ID_JSON_PROPERTY = "languageId"; | ||
|
@@ -70,6 +71,7 @@ public String getName() { | |
|
||
private String configuration; | ||
private String initializationOptions; | ||
private String clientConfiguration; | ||
|
||
public String getName() { | ||
return name; | ||
|
@@ -150,4 +152,11 @@ public void setInitializationOptions(String initializationOptions) { | |
this.initializationOptions = initializationOptions; | ||
} | ||
|
||
public String getClientConfiguration() { | ||
return clientConfiguration; | ||
} | ||
|
||
public void setClientConfiguration(String clientConfiguration) { | ||
this.clientConfiguration = clientConfiguration; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's obviously going to be a proliferation of these types of changes where I've added
clientConfiguration
as another property ofUserDefinedLanguageServerDefinition
and its peer types/methods/etc.