[syntax] prepare syntax for JS target

GitOrigin-RevId: 32c9b48b912025b7f5180572a79c2e387d9d1429
This commit is contained in:
Alexander Zolotov
2025-08-16 07:58:29 +00:00
committed by intellij-monorepo-bot
parent a5a43f10aa
commit 108a51c7da
27 changed files with 180 additions and 54 deletions
@@ -38,5 +38,5 @@ object JavaSyntaxBundle {
@ApiStatus.Internal
object DefaultJavaSyntaxResourcesTestAccessor {
val mappings: Map<String, String> get() = DefaultJavaSyntaxResources.mappings
val defaultJavaSyntaxResourcesName: String get() = DefaultJavaSyntaxResources::class.qualifiedName!!
const val defaultJavaSyntaxResourcesName: String = "com.intellij.java.syntax.DefaultJavaSyntaxResources"
}
@@ -1,9 +0,0 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.syntax
import com.intellij.platform.syntax.Logger
import com.intellij.platform.syntax.util.log.logger
internal object JavaSyntaxLog {
val log: Logger = logger<JavaSyntaxLog>()
}
@@ -3,7 +3,7 @@ package com.intellij.java.syntax.element
import com.intellij.platform.syntax.LazyParsingContext
import com.intellij.platform.syntax.extensions.ExtensionPointKey
import com.intellij.platform.syntax.extensions.ExtensionSupport
import com.intellij.platform.syntax.extensions.currentExtensionSupport
import com.intellij.platform.syntax.tree.SyntaxNode
import com.intellij.pom.java.LanguageLevel
import org.jetbrains.annotations.ApiStatus
@@ -17,7 +17,7 @@ interface JavaLanguageLevelProvider {
}
internal fun getLanguageLevel(parsingContext: LazyParsingContext): LanguageLevel {
val languageLevelProvider = ExtensionSupport().getExtensions(languageLevelExtensionPoint).firstOrNull()
val languageLevelProvider = currentExtensionSupport().getExtensions(languageLevelExtensionPoint).firstOrNull()
val languageLevel = languageLevelProvider?.getLanguageLevel(parsingContext.node) ?: LanguageLevel.HIGHEST
return languageLevel
}
@@ -256,10 +256,10 @@
- a:changeMarkerCount(I,I,I):V
- a:substitute(I,I,com.intellij.platform.syntax.tree.ASTMarkers):V
*f:com.intellij.platform.syntax.tree.ASTMarkersKt
- sf:ChameleonRef():com.intellij.platform.syntax.tree.ChameleonRef
- sf:ChameleonRef(com.intellij.platform.syntax.tree.AstMarkersChameleon):com.intellij.platform.syntax.tree.ChameleonRef
- sf:firstChild(com.intellij.platform.syntax.tree.ASTMarkers,I):I
- sf:lastChild(com.intellij.platform.syntax.tree.ASTMarkers,I):I
- sf:newChameleonRef():com.intellij.platform.syntax.tree.ChameleonRef
- sf:newChameleonRef(com.intellij.platform.syntax.tree.AstMarkersChameleon):com.intellij.platform.syntax.tree.ChameleonRef
- sf:nextSibling(com.intellij.platform.syntax.tree.ASTMarkers,I):I
- sf:prevSibling(com.intellij.platform.syntax.tree.ASTMarkers,I):I
*f:com.intellij.platform.syntax.tree.AstMarkersChameleon
@@ -22,11 +22,10 @@ interface ChameleonRef {
fun realize(func: () -> AstMarkersChameleon): AstMarkersChameleon
}
@Suppress("unused")
fun ChameleonRef(): ChameleonRef = linkToActual()
fun newChameleonRef(): ChameleonRef = linkToActual()
@Suppress("unused")
fun ChameleonRef(chameleon: AstMarkersChameleon): ChameleonRef = linkToActual()
fun newChameleonRef(chameleon: AstMarkersChameleon): ChameleonRef = linkToActual()
@ApiStatus.Experimental
interface ASTMarkers {
@@ -107,7 +107,7 @@ fun SyntaxTreeBuilder.toAstMarkers(): ASTMarkers {
item.getNodeType()
)
if (item.getNodeType().isLazyParseable() && item.isCollapsed()) {
astMarkersResult.setChameleon(item.startIndex, ChameleonRef())
astMarkersResult.setChameleon(item.startIndex, newChameleonRef())
isInsideChameleon = true
}
astTreeIndices.push(astTreeIndex)
@@ -117,7 +117,7 @@ fun SyntaxTreeBuilder.toAstMarkers(): ASTMarkers {
}
for (i in 0..<tokens.tokenCount) {
if (tokens.getTokenType(i)?.isLazyParseable() == true)
astMarkersResult.setChameleon(i, ChameleonRef())
astMarkersResult.setChameleon(i, newChameleonRef())
}
return astMarkersResult
}
@@ -0,0 +1,13 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.syntax.impl.builder
import fleet.util.multiplatform.Actual
/**
* Wasm implementation of [makeStackTraceRelative]
*/
@Suppress("unused")
@Actual("makeStackTraceRelative")
internal fun makeStackTraceRelativeJs(th: Throwable, relativeTo: Throwable): Throwable {
return th
}
@@ -0,0 +1,32 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.syntax.tree
import fleet.util.multiplatform.Actual
private class ChameleonRefImpl(private var ref: AstMarkersChameleon? = null) : ChameleonRef {
override val value: AstMarkersChameleon?
get() = ref
override fun set(value: AstMarkersChameleon) {
ref = value
}
override fun realize(func: () -> AstMarkersChameleon): AstMarkersChameleon =
ref ?: func().also { ref = it }
override fun toString(): String = ref?.toString() ?: "null"
}
/**
* Wasm implementation of [newChameleonRef].
*/
@Suppress("unused")
@Actual("ChameleonRef")
internal fun newChameleonRefJs(): ChameleonRef = ChameleonRefImpl()
/**
* Wasm implementation of [newChameleonRef].
*/
@Suppress("unused")
@Actual("ChameleonRef")
internal fun newChameleonRefJs(chameleon: AstMarkersChameleon): ChameleonRef = ChameleonRefImpl(chameleon)
@@ -23,15 +23,15 @@ private class ChameleonRefImpl(
}
/**
* Jvm implementation of [ChameleonRef].
* Jvm implementation of [newChameleonRef].
*/
@Suppress("unused")
@Actual("ChameleonRef")
internal fun ChameleonRefJvm(): ChameleonRef = ChameleonRefImpl()
internal fun newChameleonRefJvm(): ChameleonRef = ChameleonRefImpl()
/**
* Jvm implementation of [ChameleonRef].
* Jvm implementation of [newChameleonRef].
*/
@Suppress("unused")
@Actual("ChameleonRef")
internal fun ChameleonRefJvm(chameleon: AstMarkersChameleon): ChameleonRef = ChameleonRefImpl(SoftReference(chameleon))
internal fun newChameleonRefJvm(chameleon: AstMarkersChameleon): ChameleonRef = ChameleonRefImpl(SoftReference(chameleon))
@@ -22,11 +22,11 @@ private class ChameleonRefImpl(private var ref: AstMarkersChameleon? = null) : C
*/
@Suppress("unused")
@Actual("ChameleonRef")
internal fun ChameleonRefWasmJs(): ChameleonRef = ChameleonRefImpl()
internal fun newChameleonRefWasmJs(): ChameleonRef = ChameleonRefImpl()
/**
* Wasm implementation of [ChameleonRef].
*/
@Suppress("unused")
@Actual("ChameleonRef")
internal fun ChameleonRefWasmJs(chameleon: AstMarkersChameleon): ChameleonRef = ChameleonRefImpl(chameleon)
internal fun newChameleonRefWasmJs(chameleon: AstMarkersChameleon): ChameleonRef = ChameleonRefImpl(chameleon)
@@ -3,7 +3,7 @@ package com.intellij.platform.syntax.impl.builder
import com.intellij.platform.syntax.element.SyntaxTokenTypes
import com.intellij.platform.syntax.tree.ASTMarkersImpl
import com.intellij.platform.syntax.tree.ChameleonRef
import com.intellij.platform.syntax.tree.newChameleonRef
import com.intellij.platform.syntax.tree.MarkerKind
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
@@ -233,7 +233,7 @@ class ASTMarkersTests {
@Test
fun testSubstituteChameleonRemoved() {
val atomicReference = ChameleonRef()
val atomicReference = newChameleonRef()
val firstTree = ASTMarkersImpl().apply {
pushBack()
setMarker(0, 0, MarkerKind.Start, false, null, null)
@@ -319,7 +319,7 @@ class ASTMarkersTests {
setMarker(3, 0, MarkerKind.End, false, null, null)
}
val atomicReference = ChameleonRef()
val atomicReference = newChameleonRef()
val secondTree = ASTMarkersImpl().apply {
pushBack()
setMarker(0, 0, MarkerKind.Start, false, null, null)
@@ -14,8 +14,8 @@
- a:getExtensions(com.intellij.platform.syntax.extensions.ExtensionPointKey):java.util.List
- a:getLanguageExtensions(com.intellij.platform.syntax.extensions.ExtensionPointKey,com.intellij.platform.syntax.SyntaxLanguage):java.util.List
*f:com.intellij.platform.syntax.extensions.ExtensionSupportKt
- *sf:ExtensionRegistry():com.intellij.platform.syntax.extensions.ExtensionRegistry
- *sf:ExtensionSupport():com.intellij.platform.syntax.extensions.ExtensionSupport
- sf:buildExtensionSupport(kotlin.jvm.functions.Function1):com.intellij.platform.syntax.extensions.ExtensionSupport
- *sf:currentExtensionRegistry():com.intellij.platform.syntax.extensions.ExtensionRegistry
- *sf:currentExtensionSupport():com.intellij.platform.syntax.extensions.ExtensionSupport
- sf:performWithExtensionSupport(com.intellij.platform.syntax.extensions.ExtensionSupport,kotlin.jvm.functions.Function1):java.lang.Object
*:com.intellij.platform.syntax.extensions.StaticExtensionSupport
@@ -12,16 +12,16 @@ import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
/**
* Provides the current instance of [ExtensionRegistry].
* Provides the current instance of [currentExtensionRegistry].
*/
@ApiStatus.Experimental
fun ExtensionSupport(): ExtensionSupport = registry
fun currentExtensionSupport(): ExtensionSupport = registry
/**
* Provides the current instance of [ExtensionRegistry] or `null` if it is not supported in the current environment (i.e., in IntelliJ runtime).
* Provides the current instance of [currentExtensionRegistry] or `null` if it is not supported in the current environment (i.e., in IntelliJ runtime).
*/
@ApiStatus.Experimental
fun ExtensionRegistry(): ExtensionRegistry? = registry as? ExtensionRegistry
fun currentExtensionRegistry(): ExtensionRegistry? = registry as? ExtensionRegistry
/**
* Provides access for extensions registered in the current container.
@@ -3,6 +3,7 @@ package com.intellij.platform.syntax.extensions.impl
import com.intellij.platform.syntax.extensions.ExtensionRegistry
import com.intellij.platform.syntax.extensions.ExtensionSupport
import com.intellij.platform.syntax.extensions.currentExtensionSupport
import com.intellij.platform.syntax.extensions.StaticExtensionSupport
import fleet.util.multiplatform.linkToActual
import kotlin.contracts.ExperimentalContracts
@@ -28,7 +29,7 @@ internal val staticRegistryHolder: RegistryHolder by lazy {
/**
* Tries to find [com.intellij.platform.syntax.psi.IntelliJExtensionSupport] in the class path.
* If it succeeds, it means we are running in IntelliJ, and we must use IJ plugin model as the [ExtensionSupport] backend.
* If it succeeds, it means we are running in IntelliJ, and we must use IJ plugin model as the [currentExtensionSupport] backend.
* Otherwise, returning [ExtensionRegistryImpl].
*
* @See instantiateExtensionRegistryJvm
@@ -0,0 +1,18 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.syntax.extensions.impl
import fleet.util.multiplatform.Actual
/** WasmJs implementation of [newConcurrentMap] */
@Suppress("unused")
@Actual(linkedTo = "newConcurrentMap")
internal fun <K : Any, V : Any> newConcurrentMapJs(): ConcurrentMap<K, V> =
SyntaxConcurrentMapJs(HashMap())
private class SyntaxConcurrentMapJs<K : Any, V : Any>(
private val map: HashMap<K, V>,
) : MutableMap<K, V> by map, ConcurrentMap<K, V> {
override fun computeIfAbsent(key: K, f: (K) -> V): V =
map[key] ?: f(key).also { map[key] = it }
}
@@ -0,0 +1,8 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.syntax.extensions.impl
import com.intellij.platform.syntax.extensions.ExtensionSupport
import fleet.util.multiplatform.Actual
@Actual("instantiateExtensionRegistry")
internal fun instantiateExtensionRegistryJs(): ExtensionSupport = ExtensionRegistryImpl()
@@ -0,0 +1,20 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.syntax.extensions.impl
internal object ThreadLocalRegistryHolderJs : com.intellij.platform.syntax.extensions.impl.RegistryHolder {
private var threadLocal: com.intellij.platform.syntax.extensions.ExtensionSupport? = null
override val registry: com.intellij.platform.syntax.extensions.ExtensionSupport?
get() = threadLocal
override fun installRegistry(registry: com.intellij.platform.syntax.extensions.ExtensionSupport) {
threadLocal = registry
}
}
/**
* @see getThreadLocalRegistry
*/
@fleet.util.multiplatform.Actual("instantiateThreadLocalRegistry")
internal fun instantiateThreadLocalRegistryJs(): com.intellij.platform.syntax.extensions.impl.RegistryHolder =
ThreadLocalRegistryHolderJs
@@ -0,0 +1,15 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.syntax.i18n
import fleet.util.multiplatform.Actual
/**
* see expect function [com.intellij.platform.syntax.i18n.ResourceBundle]
*/
@Actual("ResourceBundle")
internal fun ResourceBundleJs(
bundleClass: String,
pathToBundle: String,
self: Any,
defaultMapping: Map<String, String>,
): ResourceBundle = BaseResourceBundle(defaultMapping)
@@ -6,7 +6,7 @@ import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.VirtualFileManagerListener
import com.intellij.platform.syntax.extensions.ExtensionPointKey
import com.intellij.platform.syntax.extensions.ExtensionSupport
import com.intellij.platform.syntax.extensions.currentExtensionSupport
import com.intellij.testFramework.junit5.TestApplication
import com.intellij.testFramework.registerExtension
import org.junit.jupiter.api.AfterEach
@@ -32,7 +32,7 @@ class IntelliJExtensionSupportTest {
@Test
fun testSupport() {
val extensionSupport = ExtensionSupport()
val extensionSupport = currentExtensionSupport()
val pointKey = ExtensionPointKey<VirtualFileManagerListener>("com.intellij.virtualFileManagerListener")
val extensions = extensionSupport.getExtensions(pointKey)
@@ -596,7 +596,7 @@ private fun substitute(
val contextKey = key + syntaxNode.context.startLexemeIndex
val newKey = if (contextKey >= syntaxNode.endLexemeIndex) key + diff else key
if (contextKey == syntaxNode.startLexemeIndex) {
newKey to ChameleonRef(parsedChameleon)
newKey to newChameleonRef(parsedChameleon)
}
else {
newKey to value
@@ -637,7 +637,7 @@ private fun substitute(
else oldParsedChameleon.customLexemeStore
val newParsedChameleon = AstMarkersChameleon(newTokens, ast = reparsedAst)
diff = if (theSameTokens) diff else 0
lexemeIndex to ChameleonRef(newParsedChameleon)
lexemeIndex to newChameleonRef(newParsedChameleon)
}
else -> (lexemeIndex + diff) to ref
@@ -7,7 +7,7 @@ import com.intellij.platform.syntax.CancellationProvider
import com.intellij.platform.syntax.Logger
import com.intellij.platform.syntax.SyntaxElementTypeSet
import com.intellij.platform.syntax.element.SyntaxTokenTypes
import com.intellij.platform.syntax.extensions.ExtensionSupport
import com.intellij.platform.syntax.extensions.currentExtensionSupport
import com.intellij.platform.syntax.lexer.Lexer
import com.intellij.platform.syntax.lexer.TokenList
import com.intellij.platform.syntax.lexer.buildTokenList
@@ -82,6 +82,6 @@ fun parse(
builderFactory = SyntaxBuilderFactory { text, tokens, startLexeme ->
createBuilder(text, tokens, startLexeme)
},
extensions = ::ExtensionSupport
extensions = ::currentExtensionSupport
)
}
@@ -5,7 +5,7 @@ package com.intellij.platform.syntax.util.cancellation
import com.intellij.platform.syntax.CancellationProvider
import com.intellij.platform.syntax.extensions.ExtensionPointKey
import com.intellij.platform.syntax.extensions.ExtensionSupport
import com.intellij.platform.syntax.extensions.currentExtensionSupport
import org.jetbrains.annotations.ApiStatus
/**
@@ -13,7 +13,7 @@ import org.jetbrains.annotations.ApiStatus
*/
@ApiStatus.Experimental
fun cancellationProvider(): CancellationProvider? =
ExtensionSupport().getExtensions(cancellationProviderEP).firstNotNullOfOrNull { it.getCancellationProvider() }
currentExtensionSupport().getExtensions(cancellationProviderEP).firstNotNullOfOrNull { it.getCancellationProvider() }
/**
* Implement this extension point to provide a [CancellationProvider] for your environment.
@@ -7,7 +7,7 @@ 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 com.intellij.platform.syntax.extensions.currentExtensionSupport
import org.jetbrains.annotations.ApiStatus
/**
@@ -44,7 +44,7 @@ fun SyntaxElementLanguageProvider.getLanguage(elementType: SyntaxElementType): S
*/
@ApiStatus.Experimental
fun syntaxElementLanguageProvider(): SyntaxElementLanguageProvider? {
val languageProviders = ExtensionSupport().getExtensions(syntaxElementLanguageProviderEP)
val languageProviders = currentExtensionSupport().getExtensions(syntaxElementLanguageProviderEP)
if (languageProviders.isEmpty()) return null
if (languageProviders.size == 1) return languageProviders[0]
@@ -74,7 +74,7 @@ abstract class MergingLexerAdapterBase(original: Lexer) : DelegateLexer(original
}
override fun toString(): String {
return "${this::class.qualifiedName}[$delegate]"
return "${this::class.simpleName}[$delegate]"
}
override fun getCurrentPosition(): LexerPosition =
@@ -5,7 +5,7 @@ package com.intellij.platform.syntax.util.log
import com.intellij.platform.syntax.Logger
import com.intellij.platform.syntax.extensions.ExtensionPointKey
import com.intellij.platform.syntax.extensions.ExtensionSupport
import com.intellij.platform.syntax.extensions.currentExtensionSupport
import com.intellij.platform.syntax.logger.noopLogger
import org.jetbrains.annotations.ApiStatus
@@ -14,13 +14,7 @@ import org.jetbrains.annotations.ApiStatus
*/
@ApiStatus.Experimental
fun logger(name: String): Logger =
ExtensionSupport().getExtensions(logProviderExtensionPoint).firstNotNullOfOrNull { it.getLogger(name) } ?: noopLogger()
/**
* Provides a [Logger] for your environment with the qualified name of the receiver class, or [noopLogger] if no Logger was provided.
*/
@ApiStatus.Experimental
inline fun <reified T> logger(): Logger = logger(T::class.qualifiedName!!)
currentExtensionSupport().getExtensions(logProviderExtensionPoint).firstNotNullOfOrNull { it.getLogger(name) } ?: noopLogger()
/**
* Implement this extension point to provide a [Logger] for your environment with the given name..
@@ -0,0 +1,20 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util.text
import fleet.util.multiplatform.Actual
/**
* [com.intellij.util.text.fromSequenceWithoutCopyingPlatformSpecific]
*/
@Actual("fromSequenceWithoutCopyingPlatformSpecific")
internal fun fromSequenceWithoutCopyingPlatformSpecificJs(seq: CharSequence?): CharArray? {
return null
}
/**
* [com.intellij.util.text.getCharsPlatformSpecific]
*/
@Actual("getCharsPlatformSpecific")
internal fun getCharsPlatformSpecificJs(string: CharSequence, srcOffset: Int, dst: CharArray, dstOffset: Int, len: Int): Boolean {
return false
}
@@ -0,0 +1,15 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util
import com.intellij.util.lang.JavaVersion
import fleet.util.multiplatform.Actual
import org.jetbrains.annotations.ApiStatus
/**
* actual for [com.intellij.util.currentJavaVersionPlatformSpecific]
*/
@Actual("currentJavaVersionPlatformSpecific")
@ApiStatus.Internal
fun currentJavaVersionPlatformSpecificJs(): JavaVersion {
return JavaVersion.compose(21, 0, 0, 0, false)
}