Repository navigation
IntelliJ stability update #50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
38e8d2b
226e840
4f6ab88
b7cde80
e61091a
1cbd63b
bdc9c22
2266d28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,19 +5,28 @@ | |||||||
| import com.codacy.intellij.plugin.services.api.Api | ||||||||
| import com.codacy.intellij.plugin.services.cli.CodacyCliService | ||||||||
| import com.codacy.intellij.plugin.services.common.Config | ||||||||
| import com.codacy.intellij.plugin.services.common.Logger | ||||||||
| import com.codacy.intellij.plugin.services.common.GitRemoteParser | ||||||||
| import com.codacy.intellij.plugin.services.common.IconUtils | ||||||||
| import com.codacy.intellij.plugin.services.git.GitProvider | ||||||||
| import com.codacy.intellij.plugin.services.git.RepositoryManager | ||||||||
| import com.codacy.intellij.plugin.telemetry.ExtensionInstalledEvent | ||||||||
| import com.codacy.intellij.plugin.telemetry.Telemetry | ||||||||
| import com.codacy.intellij.plugin.views.invalidateAnalysisCacheForHash | ||||||||
| import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer | ||||||||
| import com.intellij.ide.plugins.DynamicPluginListener | ||||||||
| import com.intellij.openapi.Disposable | ||||||||
| import com.intellij.openapi.application.ApplicationManager | ||||||||
| import com.intellij.openapi.components.service | ||||||||
| import com.intellij.openapi.project.Project | ||||||||
| import com.intellij.openapi.util.Disposer | ||||||||
| import com.intellij.openapi.startup.StartupActivity | ||||||||
| import com.intellij.openapi.vfs.VirtualFileManager | ||||||||
| import com.intellij.openapi.vfs.newvfs.BulkFileListener | ||||||||
| import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent | ||||||||
| import com.intellij.openapi.vfs.newvfs.events.VFileEvent | ||||||||
| import com.intellij.psi.PsiDocumentManager | ||||||||
| import com.intellij.psi.PsiManager | ||||||||
| import git4idea.repo.GitRepository | ||||||||
| import git4idea.repo.GitRepositoryChangeListener | ||||||||
| import kotlinx.coroutines.* | ||||||||
|
|
@@ -26,12 +35,26 @@ | |||||||
|
|
||||||||
| companion object { | ||||||||
| private const val MIN_REFRESH_INTERVAL_MS = 5000L | ||||||||
| private val activeScopes = java.util.Collections.synchronizedList(mutableListOf<CoroutineScope>()) | ||||||||
|
|
||||||||
| fun cancelAllScopes() { | ||||||||
| synchronized(activeScopes) { | ||||||||
| activeScopes.forEach { it.cancel() } | ||||||||
| activeScopes.clear() | ||||||||
| } | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| private var lastTriggeredTime = 0L | ||||||||
|
|
||||||||
| @OptIn(DelicateCoroutinesApi::class) | ||||||||
| override fun runActivity(project: Project) { | ||||||||
| val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) | ||||||||
| activeScopes.add(scope) | ||||||||
| Disposer.register(project, Disposable { | ||||||||
| scope.cancel() | ||||||||
| activeScopes.remove(scope) | ||||||||
| }) | ||||||||
|
|
||||||||
| // Check for first installation | ||||||||
| val config = Config.instance | ||||||||
| if (config.state.isFirstRun) { | ||||||||
|
|
@@ -48,30 +71,53 @@ | |||||||
| connection.subscribe(DynamicPluginListener.TOPIC, PluginStateListener()) | ||||||||
|
|
||||||||
| connection.subscribe(GitRepository.GIT_REPO_CHANGE, GitRepositoryChangeListener { repository -> | ||||||||
| val gitResult = initializeGit(project, scope) | ||||||||
|
|
||||||||
| if (gitResult == null) { | ||||||||
| Logger.info("No git remote found, initializing services without remote info.") | ||||||||
| CodacyCliService.getServiceWithoutRemote(project) | ||||||||
| AiAgentService.getServiceWithoutRemote(project) | ||||||||
| } else { | ||||||||
| val repositoryManager = gitResult.first | ||||||||
| val gitInfo = gitResult.second | ||||||||
|
|
||||||||
| val gitResult = initializeGit(project) | ||||||||
| val repositoryManager = gitResult.first | ||||||||
| val gitInfo = gitResult.second | ||||||||
| CodacyCliService.getService( | ||||||||
| Provider.fromString(gitInfo.provider), gitInfo.organization, gitInfo.repository, project, | ||||||||
| ) | ||||||||
|
|
||||||||
| CodacyCliService.getService( | ||||||||
| Provider.fromString(gitInfo.provider), gitInfo.organization, gitInfo.repository, project, | ||||||||
| ) | ||||||||
| AiAgentService.getService(project) | ||||||||
|
|
||||||||
| AiAgentService.getService(project) | ||||||||
| scope.launch { | ||||||||
| try { | ||||||||
| service<Api>().listTools() | ||||||||
| } catch (e: Exception) { | ||||||||
| Logger.warn("Failed to load tools: ${e.message}") | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| GlobalScope.launch { | ||||||||
| Api().listTools() | ||||||||
| if (repository.currentBranch != null) { | ||||||||
| scope.launch { | ||||||||
| repositoryManager.handleStateChange() | ||||||||
| } | ||||||||
| } else { | ||||||||
| repositoryManager.notifyDidChangeConfig() | ||||||||
| } | ||||||||
| } | ||||||||
| }) | ||||||||
|
|
||||||||
| if (repository.currentBranch != null) { | ||||||||
| CoroutineScope(Dispatchers.Default).launch { | ||||||||
| repositoryManager.handleStateChange() | ||||||||
| } | ||||||||
| // Perform initial startup initialization without waiting for a git change event | ||||||||
| val gitRepository = GitProvider.getRepository(project) | ||||||||
| if (gitRepository != null) { | ||||||||
| val gitResult = initializeGit(project, scope) | ||||||||
| if (gitResult == null) { | ||||||||
| CodacyCliService.getServiceWithoutRemote(project) | ||||||||
| AiAgentService.getServiceWithoutRemote(project) | ||||||||
| } else { | ||||||||
| repositoryManager.notifyDidChangeConfig() | ||||||||
| val (_, gitInfo) = gitResult | ||||||||
| CodacyCliService.getService(Provider.fromString(gitInfo.provider), gitInfo.organization, gitInfo.repository, project) | ||||||||
| AiAgentService.getService(project) | ||||||||
| } | ||||||||
| }) | ||||||||
| } | ||||||||
|
|
||||||||
| connection.subscribe(VirtualFileManager.VFS_CHANGES, object : BulkFileListener { | ||||||||
| private fun handle(events: List<VFileEvent>) { | ||||||||
|
|
@@ -91,20 +137,18 @@ | |||||||
|
|
||||||||
| override fun after(events: List<VFileEvent>) { | ||||||||
| handle(events) | ||||||||
| triggerAnalysisForSavedFiles(project, events) | ||||||||
| } | ||||||||
| }) | ||||||||
| } | ||||||||
|
|
||||||||
| @OptIn(DelicateCoroutinesApi::class) | ||||||||
| private fun initializeGit(project: Project): Pair<RepositoryManager, GitRemoteParser.GitRemoteInfo> { | ||||||||
| private fun initializeGit(project: Project, scope: CoroutineScope): Pair<RepositoryManager, GitRemoteParser.GitRemoteInfo>? { | ||||||||
| val gitRepository = GitProvider.getRepository(project) | ||||||||
| val repositoryManager = project.service<RepositoryManager>() | ||||||||
| if (gitRepository != null && repositoryManager.currentRepository != gitRepository) | ||||||||
| GlobalScope.launch { repositoryManager.open(gitRepository) } | ||||||||
|
|
||||||||
| val remote = gitRepository?.remotes?.firstOrNull() | ||||||||
| ?: throw IllegalStateException("No remote found in the Git repository") | ||||||||
| scope.launch { repositoryManager.open(gitRepository) } | ||||||||
|
|
||||||||
| val remote = gitRepository?.remotes?.firstOrNull() ?: return null | ||||||||
| val gitInfo = GitRemoteParser.parseGitRemote(remote.firstUrl!!) | ||||||||
|
||||||||
| val gitInfo = GitRemoteParser.parseGitRemote(remote.firstUrl!!) | |
| val remoteUrl = remote.firstUrl ?: return null | |
| val gitInfo = GitRemoteParser.parseGitRemote(remoteUrl) |
Check warning on line 185 in src/main/kotlin/com/codacy/intellij/plugin/listeners/StartupListener.kt
Codacy Production / Codacy Static Code Analysis
src/main/kotlin/com/codacy/intellij/plugin/listeners/StartupListener.kt#L185
Expression with labels increase complexity and affect maintainability.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -78,6 +78,13 @@ class AiAgentService { | |
|
|
||
| return service | ||
| } | ||
|
|
||
| fun getServiceWithoutRemote(project: Project): AiAgentService { | ||
| val pathsBehaviour = PathsBehaviour.Factory.build() | ||
| val service = project.getService(AiAgentService::class.java) | ||
| service.initService(Provider.GITHUB, "", "", project, pathsBehaviour) | ||
| return service | ||
|
Comment on lines
+82
to
+86
|
||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,7 +13,7 @@ import java.io.InputStreamReader | |
| import java.net.HttpURLConnection | ||
| import java.net.URL | ||
|
|
||
| @Service | ||
| @Service(Service.Level.APP) | ||
| class Api { | ||
|
|
||
| private val config = service<Config>() | ||
|
|
@@ -47,15 +47,13 @@ class Api { | |
| Gson().fromJson(response, responseClass) | ||
| } | ||
| } else { | ||
| Logger.error("Failed to fetch data: HTTP response code $responseCode") | ||
| if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) | ||
| config.storeApiToken("") | ||
| throw Exception("Failed to fetch data: HTTP response code $responseCode") | ||
| } | ||
|
Comment on lines
49
to
53
|
||
| } | ||
| catch (e: Exception) { | ||
|
lventura-codacy marked this conversation as resolved.
|
||
| Logger.error("Failed to fetch data: ${e.message}") | ||
| responseClass.newInstance() | ||
| throw Exception("Failed to fetch data: ${e.message}", e) | ||
| } | ||
|
lventura-codacy marked this conversation as resolved.
|
||
| } | ||
| } | ||
|
|
@@ -131,7 +129,7 @@ class Api { | |
| return try { | ||
| makeRequest(endpointUrl, GetUserProfileResponse::class.java).data | ||
| } catch (e: Exception) { | ||
| Logger.error("Failed to fetch user profile: ${e.message}") | ||
| Logger.warn("Failed to fetch user profile: ${e.message}") | ||
| null | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ import com.codacy.intellij.plugin.services.common.Config.Companion.CODACY_TOOLS_ | |
| import com.codacy.intellij.plugin.services.common.Config.Companion.CODACY_YAML_NAME | ||
| import com.codacy.intellij.plugin.services.common.GitRemoteParser | ||
| import com.codacy.intellij.plugin.services.common.IconUtils | ||
| import com.codacy.intellij.plugin.services.common.Logger | ||
| import com.codacy.intellij.plugin.services.common.OsType | ||
| import com.codacy.intellij.plugin.services.common.SystemDetectionService | ||
| import com.codacy.intellij.plugin.services.git.GitProvider | ||
|
|
@@ -83,7 +84,7 @@ class CodacyCliService() { | |
|
|
||
| data object NOT_INSTALLED : CodacyCliState { | ||
| override fun toString() = "Not Installed" | ||
| override val icon: Icon = AllIcons.General.Gear | ||
| override val icon: Icon = IconUtils.CodacyIcon | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -96,7 +97,8 @@ class CodacyCliService() { | |
| private lateinit var cliBehaviour: CodacyCliBehaviour | ||
| private lateinit var pathsBehaviour: PathsBehaviour | ||
|
|
||
| private var isServiceInstantiated: Boolean = false | ||
| var isServiceInstantiated: Boolean = false | ||
| private set | ||
|
|
||
| private val cliStateListeners = mutableListOf<() -> Unit>() | ||
|
|
||
|
|
@@ -168,6 +170,10 @@ class CodacyCliService() { | |
| ) | ||
| } | ||
|
|
||
| fun getServiceWithoutRemote(project: Project): CodacyCliService { | ||
| return getService(Provider.GITHUB, "", "", project) | ||
| } | ||
|
Comment on lines
+173
to
+175
|
||
|
|
||
| fun getService( | ||
| provider: Provider, | ||
| organization: String, | ||
|
|
@@ -492,16 +498,11 @@ class CodacyCliService() { | |
| } | ||
|
|
||
| if (fileOutput.isFailure) { | ||
| notificationManager.createNotification( | ||
| "CLI tools has not generated a result file", | ||
| "Current document will not be analyzed, please try again", | ||
| NotificationType.ERROR | ||
| ).notify(project) | ||
| return@withTempFile | ||
| Logger.info("No analysis result file found for file: $file. Is it a supported file type?") | ||
| } | ||
|
|
||
| results = fileOutput.getOrNull() | ||
| .let { SarifUtil.readReport(StringReader(it)).runs } | ||
| ?.let { SarifUtil.readReport(StringReader(it)).runs } | ||
| ?.let(::processSarifResults) | ||
| ?: emptyList() | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling
CodacyCliService.getServiceWithoutRemote()/AiAgentService.getServiceWithoutRemote()here can permanently initialize those services with empty org/repo (both services’initServicemethods only set repo context on first initialization). If a remote becomes available later in the session, subsequentgetService(project)calls may not update the context. Consider not instantiating services until remote info exists, or ensure services can be re-initialized with real repo data once available.