diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/ContentTypeToLanguageServerDefinition.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/ContentTypeToLanguageServerDefinition.java index 703cefb03..53ae60854 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/ContentTypeToLanguageServerDefinition.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/ContentTypeToLanguageServerDefinition.java @@ -1,14 +1,26 @@ package com.redhat.devtools.intellij.lsp4ij; import com.intellij.lang.Language; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; import java.util.AbstractMap; public class ContentTypeToLanguageServerDefinition extends AbstractMap.SimpleEntry { - public ContentTypeToLanguageServerDefinition(@Nonnull Language language, - @Nonnull LanguageServersRegistry.LanguageServerDefinition provider) { + + private final DocumentMatcher documentMatcher; + + public ContentTypeToLanguageServerDefinition(@NotNull Language language, + @NotNull LanguageServersRegistry.LanguageServerDefinition provider, + @NotNull DocumentMatcher documentMatcher) { super(language, provider); + this.documentMatcher = documentMatcher; + } + + public boolean match(VirtualFile file, Project project) { + return documentMatcher.match(file, project); } public boolean isEnabled() { diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/DocumentMatcher.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/DocumentMatcher.java new file mode 100644 index 000000000..84847972b --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/DocumentMatcher.java @@ -0,0 +1,10 @@ +package com.redhat.devtools.intellij.lsp4ij; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; + +public interface DocumentMatcher { + + boolean match(VirtualFile file, Project project); + +} diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageMappingExtensionPointBean.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageMappingExtensionPointBean.java index 7bfedcf8a..ba1d74778 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageMappingExtensionPointBean.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageMappingExtensionPointBean.java @@ -2,9 +2,15 @@ import com.intellij.openapi.extensions.AbstractExtensionPointBean; import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.serviceContainer.BaseKeyedLazyInstance; import com.intellij.util.xmlb.annotations.Attribute; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class LanguageMappingExtensionPointBean extends BaseKeyedLazyInstance { + + private static final DocumentMatcher DEFAULT_DOCUMENT_MATCHER = (file,project) -> true; -public class LanguageMappingExtensionPointBean extends AbstractExtensionPointBean { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.redhat.devtools.intellij.quarkus.languageMapping"); @Attribute("id") @@ -15,4 +21,21 @@ public class LanguageMappingExtensionPointBean extends AbstractExtensionPointBea @Attribute("serverId") public String serverId; + + @Attribute("documentMatcher") + public String documentMatcher; + + public @NotNull DocumentMatcher getDocumentMatcher() { + try { + return super.getInstance(); + } + catch(Exception e) { + return DEFAULT_DOCUMENT_MATCHER; + } + } + + @Override + protected @Nullable String getImplementationClassName() { + return documentMatcher; + } } diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageServersRegistry.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageServersRegistry.java index 882255e1a..d6926a896 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageServersRegistry.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageServersRegistry.java @@ -20,6 +20,7 @@ import org.eclipse.lsp4j.jsonrpc.Launcher; import org.eclipse.lsp4j.jsonrpc.validation.NonNull; import org.eclipse.lsp4j.services.LanguageServer; +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -194,7 +195,7 @@ private void initialize() { for (LanguageMappingExtensionPointBean extension : LanguageMappingExtensionPointBean.EP_NAME.getExtensions()) { Language language = Language.findLanguageByID(extension.language); if (language != null) { - languageMappings.add(new LanguageMapping(language, extension.id, extension.serverId)); + languageMappings.add(new LanguageMapping(language, extension.id, extension.serverId, extension.getDocumentMatcher())); } } @@ -205,7 +206,7 @@ private void initialize() { for (LanguageMapping mapping : languageMappings) { LanguageServerDefinition lsDefinition = servers.get(mapping.languageId); if (lsDefinition != null) { - registerAssociation(mapping.language, lsDefinition, mapping.languageId); + registerAssociation(lsDefinition, mapping); } else { LOGGER.warn("server '" + mapping.id + "' not available"); //$NON-NLS-1$ //$NON-NLS-2$ } @@ -230,13 +231,14 @@ List findProviderFor(final @NonNull Langu } - public void registerAssociation(@Nonnull Language language, - @Nonnull LanguageServerDefinition serverDefinition, @Nullable String languageId) { + public void registerAssociation(@NotNull LanguageServerDefinition serverDefinition, @Nullable LanguageMapping mapping) { + @NotNull Language language = mapping.language; + @Nullable String languageId = mapping.languageId; if (languageId != null) { serverDefinition.registerAssociation(language, languageId); } - connections.add(new ContentTypeToLanguageServerDefinition(language, serverDefinition)); + connections.add(new ContentTypeToLanguageServerDefinition(language, serverDefinition, mapping.getDocumentMatcher())); } public List getContentTypeToLSPExtensions() { @@ -258,19 +260,25 @@ LanguageServerDefinition getDefinition(@NonNull String languageServerId) { */ private static class LanguageMapping { - @Nonnull + @NotNull public final String id; - @Nonnull + @NotNull public final Language language; @Nullable public final String languageId; - public LanguageMapping(@Nonnull Language language, @Nonnull String id, @Nullable String languageId) { + private final DocumentMatcher documentMatcher; + + public LanguageMapping(@NotNull Language language, @Nullable String id, @Nullable String languageId, @NotNull DocumentMatcher documentMatcher) { this.language = language; this.id = id; this.languageId = languageId; + this.documentMatcher = documentMatcher; } + public DocumentMatcher getDocumentMatcher() { + return documentMatcher; + } } /** @@ -278,19 +286,20 @@ public LanguageMapping(@Nonnull Language language, @Nonnull String id, @Nullable * @param serverDefinition * @return whether the given serverDefinition is suitable for the file */ - public boolean matches(@Nonnull VirtualFile file, @NonNull LanguageServerDefinition serverDefinition, - Project project) { - return getAvailableLSFor(LSPIJUtils.getFileLanguage(file, project)).contains(serverDefinition); - } - - /** - * @param document - * @param serverDefinition - * @return whether the given serverDefinition is suitable for the file - */ - public boolean matches(@Nonnull Document document, @Nonnull LanguageServerDefinition serverDefinition, - Project project) { - return getAvailableLSFor(LSPIJUtils.getDocumentLanguage(document, project)).contains(serverDefinition); + public boolean matches(VirtualFile file, + Project project, @Nonnull LanguageServerDefinition serverDefinition) { + Language language = LSPIJUtils.getFileLanguage(file, project); + if (language == null) { + return false; + } + for (ContentTypeToLanguageServerDefinition mapping : this.connections) { + if (language.isKindOf(mapping.getKey()) && serverDefinition.equals(mapping.getValue())) { + if (mapping.match(file, project)) { + return true; + } + } + } + return false; } diff --git a/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageServiceAccessor.java b/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageServiceAccessor.java index 3f2720ecf..a1dbddc32 100644 --- a/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageServiceAccessor.java +++ b/src/main/java/com/redhat/devtools/intellij/lsp4ij/LanguageServiceAccessor.java @@ -163,7 +163,7 @@ private Collection getLSWrappers(@NotNull VirtualFile fil res.addAll(startedServers.stream() .filter(wrapper -> { try { - return wrapper.isEnabled() && (wrapper.isConnectedTo(path) || LanguageServersRegistry.getInstance().matches(file, wrapper.serverDefinition, project)); + return wrapper.isEnabled() && (wrapper.isConnectedTo(path) || LanguageServersRegistry.getInstance().matches(file, project, wrapper.serverDefinition)); } catch (ProcessCanceledException cancellation) { throw cancellation; } catch (Exception e) { @@ -195,9 +195,11 @@ private Collection getLSWrappers(@NotNull VirtualFile fil } final Project fileProject = file != null ? LSPIJUtils.getProject(file) : null; if (fileProject != null) { - LanguageServerWrapper wrapper = new LanguageServerWrapper(fileProject, serverDefinition); - startedServers.add(wrapper); - res.add(wrapper); + if(mapping.match(file, fileProject)) { + LanguageServerWrapper wrapper = new LanguageServerWrapper(fileProject, serverDefinition); + startedServers.add(wrapper); + res.add(wrapper); + } } } processedContentTypes.add(contentType); @@ -247,7 +249,7 @@ private Collection getMatchingStartedWrappers(@NotNull Vi @Nullable Predicate request) { synchronized (startedServers) { return startedServers.stream().filter(wrapper -> wrapper.isConnectedTo(LSPIJUtils.toUri(file)) - || (LanguageServersRegistry.getInstance().matches(file, wrapper.serverDefinition, project) + || (LanguageServersRegistry.getInstance().matches(file, project, wrapper.serverDefinition) && wrapper.canOperate(LSPIJUtils.getProject(file)))).filter(wrapper -> request == null || (wrapper.getServerCapabilities() == null || request.test(wrapper.getServerCapabilities()))) .collect(Collectors.toList()); diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/AbstractQuarkusDocumentMatcher.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/AbstractQuarkusDocumentMatcher.java new file mode 100644 index 000000000..74e19d59b --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/AbstractQuarkusDocumentMatcher.java @@ -0,0 +1,18 @@ +package com.redhat.devtools.intellij.quarkus.lsp; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.redhat.devtools.intellij.lsp4ij.DocumentMatcher; +import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils; +import com.redhat.devtools.intellij.quarkus.QuarkusModuleUtil; +import com.redhat.devtools.intellij.qute.psi.utils.PsiQuteProjectUtils; + +public class AbstractQuarkusDocumentMatcher implements DocumentMatcher { + @Override + public boolean match(VirtualFile file, Project fileProject) { + Module module = LSPIJUtils.getModule(file); + return module != null && QuarkusModuleUtil.isQuarkusModule(module); + } +} \ No newline at end of file diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusDocumentMatcherForJavaFile.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusDocumentMatcherForJavaFile.java new file mode 100644 index 000000000..fc224cc52 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusDocumentMatcherForJavaFile.java @@ -0,0 +1,12 @@ +package com.redhat.devtools.intellij.quarkus.lsp; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils; +import com.redhat.devtools.intellij.quarkus.QuarkusModuleUtil; + +public class QuarkusDocumentMatcherForJavaFile extends AbstractQuarkusDocumentMatcher { + +} \ No newline at end of file diff --git a/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusDocumentMatcherForPropertiesFile.java b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusDocumentMatcherForPropertiesFile.java new file mode 100644 index 000000000..65936bcf7 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/quarkus/lsp/QuarkusDocumentMatcherForPropertiesFile.java @@ -0,0 +1,21 @@ +package com.redhat.devtools.intellij.quarkus.lsp; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.redhat.devtools.intellij.quarkus.QuarkusModuleUtil; + +public class QuarkusDocumentMatcherForPropertiesFile extends AbstractQuarkusDocumentMatcher { + + @Override + public boolean match(VirtualFile file, Project fileProject) { + if (!matchFile(file, fileProject)) { + return false; + } + return super.match(file, fileProject); + } + + private boolean matchFile(VirtualFile file, Project fileProject) { + return QuarkusModuleUtil.isQuarkusPropertiesFile(file, fileProject) || QuarkusModuleUtil.isQuarkusYAMLFile(file, fileProject); + } +} \ No newline at end of file diff --git a/src/main/java/com/redhat/devtools/intellij/qute/lang/QuteLanguageSubstitutor.java b/src/main/java/com/redhat/devtools/intellij/qute/lang/QuteLanguageSubstitutor.java index 788e0131e..ed4bb119f 100644 --- a/src/main/java/com/redhat/devtools/intellij/qute/lang/QuteLanguageSubstitutor.java +++ b/src/main/java/com/redhat/devtools/intellij/qute/lang/QuteLanguageSubstitutor.java @@ -25,6 +25,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import static com.redhat.devtools.intellij.qute.psi.utils.PsiQuteProjectUtils.isQuteTemplate; + /** * Qute language substitutor to force some language file (ex:HTML, YAML, etc) to "_Qute" language when: *
    @@ -34,7 +36,7 @@ */ public class QuteLanguageSubstitutor extends LanguageSubstitutor { protected boolean isTemplate(VirtualFile file, Module module) { - return file.getPath().contains("templates") && + return isQuteTemplate(file, module) && ModuleRootManager.getInstance(module).getFileIndex().isInSourceContent(file); } diff --git a/src/main/java/com/redhat/devtools/intellij/qute/lsp/AbstractQuteDocumentMatcher.java b/src/main/java/com/redhat/devtools/intellij/qute/lsp/AbstractQuteDocumentMatcher.java new file mode 100644 index 000000000..085cc38f2 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/qute/lsp/AbstractQuteDocumentMatcher.java @@ -0,0 +1,18 @@ +package com.redhat.devtools.intellij.qute.lsp; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.redhat.devtools.intellij.lsp4ij.DocumentMatcher; +import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils; +import com.redhat.devtools.intellij.qute.psi.utils.PsiQuteProjectUtils; + +public class AbstractQuteDocumentMatcher implements DocumentMatcher { + + @Override + public boolean match(VirtualFile file, Project fileProject) { + Module module = LSPIJUtils.getModule(file); + return module != null && PsiQuteProjectUtils.hasQuteSupport(module); + } +} \ No newline at end of file diff --git a/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteDocumentMatcherForJavaFile.java b/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteDocumentMatcherForJavaFile.java new file mode 100644 index 000000000..b3dafa861 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteDocumentMatcherForJavaFile.java @@ -0,0 +1,12 @@ +package com.redhat.devtools.intellij.qute.lsp; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.redhat.devtools.intellij.lsp4ij.DocumentMatcher; +import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils; +import com.redhat.devtools.intellij.quarkus.QuarkusModuleUtil; + +public class QuteDocumentMatcherForJavaFile extends AbstractQuteDocumentMatcher { +} \ No newline at end of file diff --git a/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteDocumentMatcherForTemplateFile.java b/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteDocumentMatcherForTemplateFile.java new file mode 100644 index 000000000..bc88fe1f5 --- /dev/null +++ b/src/main/java/com/redhat/devtools/intellij/qute/lsp/QuteDocumentMatcherForTemplateFile.java @@ -0,0 +1,20 @@ +package com.redhat.devtools.intellij.qute.lsp; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils; +import com.redhat.devtools.intellij.qute.psi.utils.PsiQuteProjectUtils; + +import static com.redhat.devtools.intellij.qute.psi.utils.PsiQuteProjectUtils.isQuteTemplate; + +public class QuteDocumentMatcherForTemplateFile extends AbstractQuteDocumentMatcher { + + @Override + public boolean match(VirtualFile file, Project fileProject) { + if (!super.match(file, fileProject)) { + return false; + } + return isQuteTemplate(file, LSPIJUtils.getModule(file)); + } +} \ No newline at end of file diff --git a/src/main/java/com/redhat/devtools/intellij/qute/psi/utils/PsiQuteProjectUtils.java b/src/main/java/com/redhat/devtools/intellij/qute/psi/utils/PsiQuteProjectUtils.java index 65d3681f2..27bbcbfbf 100644 --- a/src/main/java/com/redhat/devtools/intellij/qute/psi/utils/PsiQuteProjectUtils.java +++ b/src/main/java/com/redhat/devtools/intellij/qute/psi/utils/PsiQuteProjectUtils.java @@ -14,6 +14,8 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.vfs.VirtualFile; import com.redhat.devtools.intellij.quarkus.QuarkusModuleUtil; import com.redhat.devtools.intellij.lsp4ij.LSPIJUtils; import com.redhat.devtools.intellij.qute.psi.internal.QuteJavaConstants; @@ -121,4 +123,9 @@ public static void appendAndSlash(@NotNull StringBuilder path, @NotNull String s path.append('/'); } } + + public static boolean isQuteTemplate(VirtualFile file, Module module) { + return file.getPath().contains("templates") && + ModuleRootManager.getInstance(module).getFileIndex().isInSourceContent(file); + } } diff --git a/src/main/resources/META-INF/lsp4ij-quarkus.xml b/src/main/resources/META-INF/lsp4ij-quarkus.xml index 7394280e0..2be18868a 100644 --- a/src/main/resources/META-INF/lsp4ij-quarkus.xml +++ b/src/main/resources/META-INF/lsp4ij-quarkus.xml @@ -1,7 +1,7 @@ - - - - + + + diff --git a/src/main/resources/META-INF/lsp4ij-qute.xml b/src/main/resources/META-INF/lsp4ij-qute.xml index dd65d62f3..b1a26b051 100644 --- a/src/main/resources/META-INF/lsp4ij-qute.xml +++ b/src/main/resources/META-INF/lsp4ij-qute.xml @@ -17,8 +17,12 @@ ]]> - - + +