OPENIDE fix compile errors for 2025.3

This commit is contained in:
Nikita Iarychenko
2025-12-16 14:43:48 +04:00
parent 737229bb69
commit d47d698021
6 changed files with 165 additions and 48 deletions

View File

@@ -91,7 +91,7 @@ open class OpenIdeProperties(val communityHomeDir: Path): IdeaCommunityPropertie
override fun getOutputDirectoryName(appInfo: ApplicationInfoProperties) = "open-ide"
override fun getAdditionalPluginPaths(context: BuildContext): List<Path> {
override suspend fun getAdditionalPluginPaths(context: BuildContext): List<Path> {
return OpenIdePluginBundler.getBundlePluginPaths(context)
}
}

View File

@@ -5,7 +5,7 @@
<component xmlns="http://jetbrains.org/intellij/schema/application-info">
<version major="2025" minor="3"/>
<company name="OpenIDE" url="https://openide.ru" copyrightStart="2025"/>
<build number="IC-__BUILD__" date="__BUILD_DATE__"/> <!--majorReleaseDate="20170321"-->
<build number="IC-__BUILD__" date="__BUILD_DATE__" majorReleaseDate="20251208"/>
<logo url="/openide_logo.png"/>
<logo-eap url="/openide_logo_eap.png"/>
<icon svg="/openide.svg" svg-small="/openide_16.svg"/>

View File

@@ -1382,6 +1382,9 @@ object CommunityLibraryLicenses {
LibraryLicense("zstd-jni", libraryName = "zstd-jni", url = "https://github.com/luben/zstd-jni")
.simplifiedBsd("https://github.com/luben/zstd-jni/blob/master/LICENSE"),
LibraryLicense("sentry-java", libraryName = "io.sentry", url = "https://sentry.io/")
.mit("https://github.com/getsentry/sentry-java/blob/main/LICENSE"),
jetbrainsLibrary("ai.grazie.emb"),
jetbrainsLibrary("ai.grazie.nlp.detect"),
jetbrainsLibrary("ai.grazie.nlp.encoder.bert.uncased"),

View File

@@ -5,49 +5,87 @@
package com.intellij.internal.statistic.eventLog.connection
import com.jetbrains.fus.reporting.configuration.ConfigurationClient
import com.jetbrains.fus.reporting.model.http.StatsConnectionSettings
import com.jetbrains.fus.reporting.configuration.RegionCode
import com.jetbrains.fus.reporting.model.http.HttpClientBuilder
import com.jetbrains.fus.reporting.model.http.HttpRequestBuilder
import com.jetbrains.fus.reporting.model.serialization.Serializer
import java.util.concurrent.TimeUnit
class ConfigurationClientFactory {
companion object {
/**
* The remote client periodically downloads configuration.
* The frequency can be set, it is 10 minutes by default.
* Use the test configuration url in test cases.
* */
* The remote client periodically downloads configuration for the given recorder id,
* product code and product version.
* @param recorderId Recorder id
* @param productCode Product code
* @param productVersion Product version
* @param isTestConfiguration Set it to true to use the test configuration url,
* otherwise set it false to use the production one.
* @param httpClientBuilder FUS-client supports java http client com.jetbrains.fus.reporting.connection.JavaHttpClientBuilder,
* You can configure it or use another http client [com.jetbrains.fus.reporting.model.http.HttpClientBuilder].
* @param httpRequestBuilder FUS-client supports java http request com.jetbrains.fus.reporting.connection.JavaHttpRequestBuilder,
* You can configure it or use another http request [com.jetbrains.fus.reporting.model.http.HttpRequestBuilder].
* @param regionCode The region code for the downloading configuration,
* configuration url depends on the region code.
* Configuration template url for China region code is [com.jetbrains.fus.reporting.configuration.RegionCode.CN].
* Configuration template url for all other regions is [com.jetbrains.fus.reporting.configuration.RegionCode.ALL].
* @param cacheTimeoutMs The frequency of the downloading configuration, it is 10 minutes by default.
* @param serializer FUS-client supports jackson serialization com.jetbrains.fus.reporting.serialization.FusJacksonSerializer,
* kotlin serialization com.jetbrains.fus.reporting.serialization.FusKotlinSerializer.
* You can use own serializer implementation [com.jetbrains.fus.reporting.model.serialization.Serializer].
*/
@JvmStatic
fun create(
recorderId: String,
productCode: String,
productVersion: String,
isTestConfig: Boolean,
connectionSettings: StatsConnectionSettings,
cacheTimeoutMs: Long = TimeUnit.MINUTES.toMillis(10)
isTestConfiguration: Boolean,
httpClientBuilder: HttpClientBuilder,
httpRequestBuilder: HttpRequestBuilder,
regionCode: RegionCode = RegionCode.ALL,
cacheTimeoutMs: Long = TimeUnit.MINUTES.toMillis(10),
serializer: Serializer
): ConfigurationClient {
return createConfigurationClient(
recorderId,
productCode,
productVersion,
isTestConfiguration,
httpClientBuilder,
httpRequestBuilder,
regionCode,
cacheTimeoutMs,
serializer
)
}
private fun createConfigurationClient(
recorderId: String,
productCode: String,
productVersion: String,
isTestConfiguration: Boolean,
httpClientBuilder: HttpClientBuilder,
httpRequestBuilder: HttpRequestBuilder,
regionCode: RegionCode,
cacheTimeoutMs: Long,
serializer: Serializer
): ConfigurationClient {
val eventLogSettingsURLTemplate = "https://stats.openide.ru/storage/fus/config/v4/%s/%s.json"
val configurationUrl: String =
if (isTestConfig) {
if (isTestConfiguration) {
String.format(eventLogSettingsURLTemplate, "test/$recorderId", productCode)
} else {
String.format(eventLogSettingsURLTemplate, recorderId, productCode)
}
return RemoteConfigurationClient(configurationUrl, productCode, productVersion, connectionSettings, cacheTimeoutMs)
return RemoteConfigurationClient(
configurationUrl,
productCode,
productVersion,
httpClientBuilder.newClient(configurationUrl),
httpRequestBuilder.newGetRequest(configurationUrl),
serializer,
cacheTimeoutMs
)
}
/**
* The test client periodically downloads configuration from the given test configuration url.
* The frequency can be set, it is 10 minutes by default.
* */
@JvmStatic
fun createTest(
productCode: String,
productVersion: String,
connectionSettings: StatsConnectionSettings,
cacheTimeoutMs: Long = TimeUnit.MINUTES.toMillis(10),
configurationUrl: String
): ConfigurationClient =
RemoteConfigurationClient(configurationUrl, productCode, productVersion, connectionSettings, cacheTimeoutMs)
}
}

View File

@@ -6,8 +6,6 @@ package com.intellij.internal.statistic.eventLog.connection
import com.intellij.internal.statistic.eventLog.EventLogApplicationInfo
import com.jetbrains.fus.reporting.configuration.ConfigurationClient
import com.jetbrains.fus.reporting.configuration.ConfigurationClientFactory
import com.jetbrains.fus.reporting.configuration.RegionCode
import com.jetbrains.fus.reporting.connection.JavaHttpClientBuilder
import com.jetbrains.fus.reporting.connection.JavaHttpRequestBuilder
import com.jetbrains.fus.reporting.connection.ProxyInfo

View File

@@ -5,32 +5,27 @@
package com.intellij.internal.statistic.eventLog.connection
import com.jetbrains.fus.reporting.configuration.ConfigurationClient
import com.jetbrains.fus.reporting.connection.StatsHttpClient
import com.jetbrains.fus.reporting.connection.StatsHttpResponse
import com.jetbrains.fus.reporting.connection.StatsRequestBuilder
import com.jetbrains.fus.reporting.connection.StatsResponseProcessor
import com.jetbrains.fus.reporting.model.config.v4.Configuration
import com.jetbrains.fus.reporting.model.config.v4.ConfigurationVersion
import com.jetbrains.fus.reporting.model.exceptions.StatsResponseException
import com.jetbrains.fus.reporting.model.http.StatsConnectionSettings
import com.jetbrains.fus.reporting.serialization.FusKotlinSerializer
import com.jetbrains.fus.reporting.model.http.HttpClient
import com.jetbrains.fus.reporting.model.http.HttpRequest
import com.jetbrains.fus.reporting.model.http.HttpResponse
import com.jetbrains.fus.reporting.model.serialization.SerializationException
import com.jetbrains.fus.reporting.model.serialization.Serializer
import java.io.IOException
import java.io.InputStream
import java.nio.charset.StandardCharsets
/**
* The remote client periodically downloads configuration from the given url.
* The download frequency can be set.
* */
internal class RemoteConfigurationClient internal constructor(
override val configurationUrl: String,
override val productCode: String,
private val productVersion: String,
connectionSettings: StatsConnectionSettings,
private val httpClient: HttpClient,
private val httpRequest: HttpRequest,
private val serializer: Serializer,
cacheTimeoutMs: Long
) : ConfigurationClient() {
private val httpClient = StatsHttpClient.newClient(connectionSettings, configurationUrl)
private val httpRequest = StatsRequestBuilder.newGetRequest(connectionSettings, configurationUrl)
private val cachedConfigurationVersion: StatisticsCachingSupplier<ConfigurationVersion?> =
StatisticsCachingSupplier(::loadConfiguration, cacheTimeoutMs)
@@ -49,20 +44,20 @@ internal class RemoteConfigurationClient internal constructor(
* @throws [SerializationException] if the given JSON string is not a valid JSON input for the type [Configuration].
*/
private fun loadConfiguration(): ConfigurationVersion? {
val function = object : StatsResponseProcessor<ConfigurationVersion?> {
override fun onSucceed(response: StatsHttpResponse): ConfigurationVersion? {
val processor = object : ResponseProcessor<ConfigurationVersion?> {
override fun onSucceed(response: HttpResponse): ConfigurationVersion? {
val responseContent: InputStream? = response.read()
if (responseContent != null) {
val content = responseContent.bufferedReader(StandardCharsets.UTF_8).use { reader ->
reader.readText()
}
val configuration = FusKotlinSerializer().deserializeConfigurationV4(content)
val configuration = serializer.deserializeConfiguration(content)
return configuration.findProductVersion(productVersion)
}
return null
}
}
val statsRequestResult = StatsHttpClient(httpClient).send(function, httpRequest)
val statsRequestResult = HttpClientProcessor.send(httpClient, httpRequest, processor)
if (statsRequestResult.errorCode != -1)
throw StatsResponseException(
"Http response status code to get fus reporting " +
@@ -73,4 +68,87 @@ internal class RemoteConfigurationClient internal constructor(
)
return statsRequestResult.result
}
}
internal interface ResponseProcessor<T> {
/**
* ResponseProcessor matches [HttpResponse] to [T] on succeed
*/
@Throws(IOException::class, InterruptedException::class, SecurityException::class)
fun onSucceed(response: HttpResponse): T
}
internal object HttpClientProcessor {
/**
* Java http client sends http request [MAX_RETRIES] times,
* if response code isn't 200 with an interval between attempts [RETRY_INTERVAL].
*
* @throws[java.io.IOException] if an I/O error occurs when sending request to the server or receiving response
* from the server.
* @throws[InterruptedException] if the http client operation is interrupted.
* @throws[SecurityException] If a security manager has been installed, and it denies
* {@link java.net.URLPermission access} to the URL in the given request, or proxy if one is configured.
*
*/
@Throws(IOException::class, InterruptedException::class, SecurityException::class)
fun <T> send(httpClient: HttpClient, httpRequest: HttpRequest, processor: ResponseProcessor<T>): RequestResult<T?> {
val response = trySend(httpClient, httpRequest)
val code = response?.statusCode
if (code == SUCCESS_CODE) {
val result: T = processor.onSucceed(response)
return RequestResult.succeed(result)
} else {
return RequestResult.error(code)
}
}
@Throws(IOException::class, InterruptedException::class, SecurityException::class)
private fun trySend(httpClient: HttpClient, httpRequest: HttpRequest): HttpResponse? {
var retryCounter = 0
while (retryCounter < MAX_RETRIES) {
val response = httpClient.send(httpRequest)
retryCounter++
if (CAN_RETRY_CODES.contains(response.statusCode) && (retryCounter != MAX_RETRIES - 1)) {
Thread.sleep(RETRY_INTERVAL.toLong())
} else {
return response
}
}
return null
}
private const val SUCCESS_CODE = 200
private val CAN_RETRY_CODES: List<Int> = mutableListOf(
// Standard status codes
408, // Request Timeout
429, // Too Many Requests (RFC 6585)
500, // Internal Server Error
502, // Bad Gateway
503, // Service Unavailable
504, // Gateway Timeout
// Unofficial codes
598 // Some HTTP Proxies timeout
)
private const val MAX_RETRIES = 10
private const val RETRY_INTERVAL = 500
}
internal class RequestResult<T>(val result: T, val errorCode: Int?) {
companion object {
/**
* Get a result of type [T] if server response code is 200, error code is -1 in this case
*/
fun <T> succeed(result: T): RequestResult<T> {
return RequestResult(result, -1)
}
/**
* Get an error code if server response code isn't 200, result of type [T] is null in this case
*/
fun <T> error(error: Int?): RequestResult<T?> {
return RequestResult(null, error)
}
}
}