Introduce SyntaxElementLanguageProvider

GitOrigin-RevId: cde3c5adf106e40acebeed88f80eb25a90f4b05e
This commit is contained in:
Max Medvedev
2025-06-18 08:59:02 +00:00
committed by intellij-monorepo-bot
parent 6821c5e03b
commit 8723132ebf
2 changed files with 90 additions and 0 deletions
@@ -2,6 +2,15 @@
- a:getCancellationProvider():com.intellij.platform.syntax.CancellationProvider
*f:com.intellij.platform.syntax.util.cancellation.CancellationProviderExtensionKt
- *sf:cancellationProvider():com.intellij.platform.syntax.CancellationProvider
*f:com.intellij.platform.syntax.util.language.FiniteSyntaxElementLanguageProvider
- com.intellij.platform.syntax.util.language.SyntaxElementLanguageProvider
- <init>(com.intellij.platform.syntax.SyntaxLanguage,com.intellij.platform.syntax.SyntaxElementTypeSet):V
- getLanguages(com.intellij.platform.syntax.SyntaxElementType):kotlin.sequences.Sequence
*:com.intellij.platform.syntax.util.language.SyntaxElementLanguageProvider
- a:getLanguages(com.intellij.platform.syntax.SyntaxElementType):kotlin.sequences.Sequence
*f:com.intellij.platform.syntax.util.language.SyntaxElementLanguageProviderKt
- *sf:getLanguage(com.intellij.platform.syntax.util.language.SyntaxElementLanguageProvider,com.intellij.platform.syntax.SyntaxElementType):com.intellij.platform.syntax.SyntaxLanguage
- *sf:syntaxElementLanguageProvider():com.intellij.platform.syntax.util.language.SyntaxElementLanguageProvider
*c:com.intellij.platform.syntax.util.lexer.DelegateLexer
- com.intellij.platform.syntax.util.lexer.LexerBase
- <init>(com.intellij.platform.syntax.lexer.Lexer):V
@@ -0,0 +1,81 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
@file:ApiStatus.Experimental
package com.intellij.platform.syntax.util.language
import com.intellij.platform.syntax.SyntaxElementType
import com.intellij.platform.syntax.SyntaxElementTypeSet
import com.intellij.platform.syntax.SyntaxLanguage
import com.intellij.platform.syntax.extensions.ExtensionPointKey
import com.intellij.platform.syntax.extensions.ExtensionSupport
import org.jetbrains.annotations.ApiStatus
/**
* Specifies which languages a given element type belongs to.
*
* This information is used by [com.intellij.platform.syntax.tree.SyntaxNode] to determine the language of the node.
* If the language provider is missing or does not provide a single language for the given element type, the node will use the language of its parent.
* If the language provider is missing or does not provide a single language even for the parent, the language of the parser will be used.
*
* So you need to provide the languages for your language only if the given node tree contains several languages at once.
*
* You can register your own [SyntaxElementLanguageProvider] in [ExtensionSupport] via `com.intellij.syntax.syntaxElementLanguageProvider` extension point.
* N.B. There may be several language providers registered, in which case they are combined.
*
* @see getLanguage
* @see syntaxElementLanguageProvider
* @see FiniteSyntaxElementLanguageProvider
*/
@ApiStatus.Experimental
fun interface SyntaxElementLanguageProvider {
fun getLanguages(elementType: SyntaxElementType): Sequence<SyntaxLanguage>
}
/**
* Returns the language that the given element type belongs to or `null` if it doesn't belong to any language or if several languages are possible.
*/
@ApiStatus.Experimental
fun SyntaxElementLanguageProvider.getLanguage(elementType: SyntaxElementType): SyntaxLanguage? =
getLanguages(elementType).singleOrNull()
/**
* Returns a [SyntaxElementLanguageProvider] from the current [ExtensionSupport].
* Note that if several language providers are registered, the result provider combines them all.
*/
@ApiStatus.Experimental
fun syntaxElementLanguageProvider(): SyntaxElementLanguageProvider? {
val languageProviders = ExtensionSupport().getExtensions(syntaxElementLanguageProviderEP)
if (languageProviders.isEmpty()) return null
if (languageProviders.size == 1) return languageProviders[0]
// todo implement a more efficient way to combine FiniteSyntaxElementLanguageProviders
return SyntaxElementLanguageProvider { elementType ->
languageProviders.asSequence().flatMap { languageProvider ->
languageProvider.getLanguages(elementType)
}
}
}
/**
* A [SyntaxElementLanguageProvider] that returns the given language for all element types in the given set.
* Prefer this class over implementing your own [SyntaxElementLanguageProvider] if the set of element types is finite.
*
* @see SyntaxElementLanguageProvider
*/
@ApiStatus.Experimental
class FiniteSyntaxElementLanguageProvider(
private val language: SyntaxLanguage,
private val elementTypes: SyntaxElementTypeSet,
) : SyntaxElementLanguageProvider {
override fun getLanguages(elementType: SyntaxElementType): Sequence<SyntaxLanguage> {
return if (elementType in elementTypes) {
sequenceOf(language)
}
else {
emptySequence()
}
}
}
private val syntaxElementLanguageProviderEP = ExtensionPointKey<SyntaxElementLanguageProvider>("com.intellij.syntax.syntaxElementLanguageProvider")