前一篇 《底层到底做了什么》--- sonar-maven-plugin底层原理 里,sonar-maven-plugin项目依赖关系比较复杂,向底层递归了4、5个层包都没有找到sonar-maven-plugin项目到sonar-java项目实际执行代码分析的联系。相对而言IDEA的Sonar插件以来关系要简单的多。sonarlint-intellij项目直接依赖sonar-java项目。
上源码
import com.intellij.ide.AppLifecycleListener
class InitializeSonarLintOnStartup : AppLifecycleListener {
override fun appFrameCreated(commandLineArgs: MutableList<String>) {
SonarLintUtils.getService(BackendService::class.java).startOnce()
SonarLintUtils.getService(SonarLintHttpServer::class.java).startOnce()
}
}
插件的入口类继承了intelij-idea的接口AppLifecycleListener。
类启动了两个服务,其中SonarLintHttpServer会使用Netty启动一个http服务。
class RequestProcessor(
fun processRequest(request: Request): Response {
if (request.path == STATUS_ENDPOINT && request.method == HttpMethod.GET) {
return getStatusData(request.isTrustedOrigin)
}
if (request.path == SHOW_HOTSPOT_ENDPOINT && request.method == HttpMethod.GET) {
return processOpenInIdeRequest(request)
}
if (request.path == TOKEN_ENDPOINT && request.method == HttpMethod.POST) {
return processUserToken(request)
}
return BadRequest("Invalid path or method.")
}
这个http服务处理器只会处理三种基础请求,没有业务功能。
class BackendService @NonInjectable constructor(private val backend: SonarLintBackend) : Disposable {
constructor() : this(SonarLintBackendImpl(SonarLintIntelliJClient()))
private var initialized = false
fun startOnce() {
if (initialized) return
initialized = true
initialize()
}
private fun initialize() {
migrateStoragePath()
val serverConnections = getGlobalSettings().serverConnections
val sonarCloudConnections =
serverConnections.filter { it.isSonarCloud }.map { toSonarCloudBackendConnection(it) }
val sonarQubeConnections =
serverConnections.filter { !it.isSonarCloud }.map { toSonarQubeBackendConnection(it) }
backend.initialize(
InitializeParams(
HostInfoDto("FIXME"),
TelemetryManagerProvider.TELEMETRY_PRODUCT_KEY,
getLocalStoragePath(),
EmbeddedPlugins.findEmbeddedPlugins(),
EmbeddedPlugins.getExtraPluginsForConnectedMode(),
EmbeddedPlugins.getEmbeddedPluginsForConnectedMode(),
EmbeddedPlugins.enabledLanguagesInStandaloneMode,
EmbeddedPlugins.enabledLanguagesInConnectedMode,
false,
sonarQubeConnections,
sonarCloudConnections,
null,
false
)
)
ApplicationManager.getApplication().messageBus.connect()
.subscribe(GlobalConfigurationListener.TOPIC, object : GlobalConfigurationListener.Adapter() {
override fun applied(previousSettings: SonarLintGlobalSettings, newSettings: SonarLintGlobalSettings) {
connectionsUpdated(newSettings.serverConnections)
}
override fun changed(serverList: MutableList<ServerConnection>) {
connectionsUpdated(serverList)
}
})
ApplicationManager.getApplication().messageBus.connect()
.subscribe(ProjectManager.TOPIC, object : ProjectManagerListener {
override fun projectOpened(project: Project) {
this@BackendService.projectOpened(project)
}
override fun projectClosing(project: Project) {
this@BackendService.projectClosed(project)
}
})
}
BackendService启动过程,包括 启动SonarLintBackend、向IDEA manager注册监听修改配置事件、注册监听项目事件。
SonarLintBackend是sonarlint.core项目中类,通过sonar-java项目间接引入。
SonarLintBackend的执行流程,待补充
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。