Skip to content

Commit

Permalink
feat: server bundle
Browse files Browse the repository at this point in the history
Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
angelozerr authored and fbricon committed Dec 14, 2023
1 parent 4bf333e commit f1ce819
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -1,26 +1,51 @@
/*******************************************************************************
* Copyright (c) 2020 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.devtools.lsp4ij;

import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.RequiredElement;
import com.intellij.serviceContainer.BaseKeyedLazyInstance;
import com.intellij.util.xmlb.annotations.Attribute;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* Language mapping extension point.
*/
public class LanguageMappingExtensionPointBean extends BaseKeyedLazyInstance<DocumentMatcher> {

private static final DocumentMatcher DEFAULT_DOCUMENT_MATCHER = (file,project) -> true;

public static final ExtensionPointName<LanguageMappingExtensionPointBean> EP_NAME = ExtensionPointName.create("com.redhat.devtools.lsp4ij.languageMapping");

@Attribute("id")
public String id;

/**
* The language mapped with the language server {{@link #serverId}server id}.
*/
@Attribute("language")
public String language;
@RequiredElement
public String languageId;

/**
* The language server mapped with the language {{@link #languageId}language id}.
*/
@Attribute("serverId")
@RequiredElement
public String serverId;

/**
* The {@link DocumentMatcher document matcher}.
*/
@Attribute("documentMatcher")
public String documentMatcher;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public void registerAssociation(@NotNull Language language, @NotNull String languageId) {
this.languageIdMappings.put(language, languageId);
public void registerAssociation(@NotNull Language language, @NotNull String serverId) {
this.languageIdMappings.put(language, serverId);
}

@NotNull
Expand Down Expand Up @@ -123,7 +123,7 @@ static class ExtensionLanguageServerDefinition extends LanguageServerDefinition
private Icon icon;

public ExtensionLanguageServerDefinition(ServerExtensionPointBean element) {
super(element.id, element.label, element.description, element.singleton, element.lastDocumentDisconnectedTimeout, element.supportsLightEdit);
super(element.id, element.getLabel(), element.getDescription(), element.singleton, element.lastDocumentDisconnectedTimeout, element.supportsLightEdit);
this.extension = element;
}

Expand Down Expand Up @@ -223,18 +223,18 @@ private void initialize() {
}
}
for (LanguageMappingExtensionPointBean extension : LanguageMappingExtensionPointBean.EP_NAME.getExtensions()) {
Language language = Language.findLanguageByID(extension.language);
Language language = Language.findLanguageByID(extension.languageId);
if (language != null) {
languageMappings.add(new LanguageMapping(language, extension.id, extension.serverId, extension.getDocumentMatcher()));
languageMappings.add(new LanguageMapping(language, extension.serverId, extension.getDocumentMatcher()));
}
}

for (LanguageMapping mapping : languageMappings) {
LanguageServerDefinition lsDefinition = serverDefinitions.get(mapping.languageId);
LanguageServerDefinition lsDefinition = serverDefinitions.get(mapping.serverId);
if (lsDefinition != null) {
registerAssociation(lsDefinition, mapping);
} else {
LOGGER.warn("server '" + mapping.id + "' not available"); //$NON-NLS-1$ //$NON-NLS-2$
LOGGER.warn("server '" + mapping.serverId + "' not available"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
Expand All @@ -251,13 +251,10 @@ List<ContentTypeToLanguageServerDefinition> findProviderFor(final @NotNull Langu
}


public void registerAssociation(@NotNull LanguageServerDefinition serverDefinition, @Nullable LanguageMapping mapping) {
public void registerAssociation(@NotNull LanguageServerDefinition serverDefinition, @NotNull LanguageMapping mapping) {
@NotNull Language language = mapping.language;
@Nullable String languageId = mapping.languageId;
if (languageId != null) {
serverDefinition.registerAssociation(language, languageId);
}

@NotNull String serverId = mapping.serverId;
serverDefinition.registerAssociation(language, serverId);
connections.add(new ContentTypeToLanguageServerDefinition(language, serverDefinition, mapping.getDocumentMatcher()));
}

Expand All @@ -266,19 +263,16 @@ public void registerAssociation(@NotNull LanguageServerDefinition serverDefiniti
*/
private static class LanguageMapping {

@NotNull
public final String id;
@NotNull
public final Language language;
@Nullable
public final String languageId;

@NotNull
public final String serverId;
@NotNull
private final DocumentMatcher documentMatcher;

public LanguageMapping(@NotNull Language language, @Nullable String id, @Nullable String languageId, @NotNull DocumentMatcher documentMatcher) {
public LanguageMapping(@NotNull Language language, @NotNull String serverId, @NotNull DocumentMatcher documentMatcher) {
this.language = language;
this.id = id;
this.languageId = languageId;
this.serverId = serverId;
this.documentMatcher = documentMatcher;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat Inc. and others.
* Copyright (c) 2020 Red Hat Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -13,31 +13,70 @@
*******************************************************************************/
package com.redhat.devtools.lsp4ij;

import com.intellij.AbstractBundle;
import com.intellij.BundleBase;
import com.intellij.DynamicBundle;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.extensions.RequiredElement;
import com.intellij.openapi.util.NlsContexts;
import com.intellij.serviceContainer.BaseKeyedLazyInstance;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.Tag;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ResourceBundle;

/**
* Server extension point.
*/
public class ServerExtensionPointBean extends BaseKeyedLazyInstance<LanguageServerFactory> {

private static final Logger LOGGER = LoggerFactory.getLogger(ServerExtensionPointBean.class);

public static final ExtensionPointName<ServerExtensionPointBean> EP_NAME = ExtensionPointName.create("com.redhat.devtools.lsp4ij.server");

/**
* The language server id used to associate language
* with 'com.redhat.devtools.lsp4ij.languageMapping' extension point.
*/
@Attribute("id")
@RequiredElement
public String id;

/**
* This attribute specifies the resource bundle that contains the specified {@link #labelKey} / {@link #descriptionKey}.
* This is another way to specify the {@link #label server label} / {@link #description server description}.
*/
@Attribute("bundle")
public String bundle;

/**
* This attribute specifies the resource key in the specified {@link #bundle}.
* This is another way to specify the {@link #label server label}.
*/
@Attribute("labelKey")
@Nls(capitalization = Nls.Capitalization.Title)
public String labelKey;

/**
* The language server label displayed on the LSP console and Language Servers preferences.
*/
@Attribute("label")
public String label;

/**
* This attribute specifies the resource key in the specified {@link #bundle}.
* This is another way to specify the {@link #description server description}.
*/
@Attribute("descriptionKey")
@Nls(capitalization = Nls.Capitalization.Sentence)
public String descriptionKey;

/**
* The language server description displayed on the LSP console and Language Servers preferences.
*/
Expand All @@ -55,6 +94,7 @@ public class ServerExtensionPointBean extends BaseKeyedLazyInstance<LanguageServ
* The {@link LanguageServerFactory} implementation used to create connection, language client and server interface.
*/
@Attribute("factoryClass")
@RequiredElement
public String factoryClass;

/**
Expand All @@ -79,4 +119,43 @@ public class ServerExtensionPointBean extends BaseKeyedLazyInstance<LanguageServ
protected @Nullable String getImplementationClassName() {
return factoryClass;
}

@NotNull
public String getLabel() {
if (label != null) {
return label;
}
label = getLocalizedString(bundle, labelKey);
if (label == null) {
label = id;
}
return label;
}

@Nullable
public String getDescription() {
if (description != null) {
return description;
}
if (bundle != null && descriptionKey != null) {
return getLocalizedString(bundle, descriptionKey);
}
return null;
}

private @Nullable @Nls String getLocalizedString(@Nullable String bundleName, String key) {
PluginDescriptor descriptor = getPluginDescriptor();
String baseName = bundleName != null ? bundleName :
bundle != null ? bundle :
descriptor.getResourceBundleBaseName();
if (baseName == null || key == null) {
if (bundleName != null) {
LOGGER.warn("Bundle key missed for " + id);
}
return null;
}
ResourceBundle resourceBundle = DynamicBundle.getResourceBundle(descriptor.getClassLoader(), baseName);
return AbstractBundle.message(resourceBundle, key);
}

}
24 changes: 13 additions & 11 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
</ul>
Learn more in the <a href="https://github.com/redhat-developer/lsp4ij/milestone/1?closed=1">changelog</a>.
]]>
</change-notes>
<description>
<![CDATA[
</change-notes>
<description>
<![CDATA[
<p>LSP4IJ is a free and open-source <a href="https://microsoft.github.io/language-server-protocol/">Language Server protocol (LSP)</a> client compatible with all flavors of IntelliJ.</p>
<p>It currently doesn't provide any useful functionality on its own but is instead used as a dependency for other extensions, willing to integrate language servers with IntelliJ products.</p>
Expand All @@ -30,27 +30,29 @@
<li>A <code>Language Servers settings page</code> to configure the LSP trace level and the debug port to use to debug the language server.</li>
</ul>
]]>
</description>
</description>

<depends>com.intellij.modules.platform</depends>
<!-- FIXME we shouldn't have a dependency to Java, this is caused by using 'LightRecordField' (e.g. in LSPIJUtils.getNavigationElement(PsiElement)) -->
<depends>com.intellij.modules.java</depends>
<depends>com.redhat.devtools.intellij.telemetry</depends>
<depends>com.intellij.modules.platform</depends>
<!-- FIXME we shouldn't have a dependency to Java, this is caused by using 'LightRecordField' (e.g. in LSPIJUtils.getNavigationElement(PsiElement)) -->
<depends>com.intellij.modules.java</depends>
<depends>com.redhat.devtools.intellij.telemetry</depends>


<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
<idea-version since-build="222"/>
<idea-version since-build="223"/>

<!-- LSP extension points -->
<extensionPoints>
<extensionPoint
name="server"
beanClass="com.redhat.devtools.lsp4ij.ServerExtensionPointBean" >
beanClass="com.redhat.devtools.lsp4ij.ServerExtensionPointBean">
<with attribute="factoryClass" implements="com.redhat.devtools.lsp4ij.LanguageServerFactory"/>
</extensionPoint>
<extensionPoint
name="languageMapping"
beanClass="com.redhat.devtools.lsp4ij.LanguageMappingExtensionPointBean"/>
beanClass="com.redhat.devtools.lsp4ij.LanguageMappingExtensionPointBean">
<with attribute="documentMatcher" implements="com.redhat.devtools.lsp4ij.DocumentMatcher"/>
</extensionPoint>
</extensionPoints>

<!-- Language Server support -->
Expand Down

0 comments on commit f1ce819

Please sign in to comment.