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 6 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,15 +5,18 @@ import com.codacy.intellij.plugin.services.agent.model.Provider | |||||||
| 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.intellij.ide.plugins.DynamicPluginListener | ||||||||
| import com.intellij.openapi.Disposable | ||||||||
| 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 | ||||||||
|
|
@@ -26,12 +29,26 @@ class StartupListener : StartupActivity { | |||||||
|
|
||||||||
| 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 +65,53 @@ class StartupListener : StartupActivity { | |||||||
| 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>) { | ||||||||
|
|
@@ -95,16 +135,13 @@ class StartupListener : StartupActivity { | |||||||
| }) | ||||||||
| } | ||||||||
|
|
||||||||
| @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) |
| 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() | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ import com.codacy.intellij.plugin.services.git.RepositoryManager.RepositoryManag | |
| import kotlinx.coroutines.* | ||
| import com.intellij.notification.* | ||
| import com.intellij.openapi.components.Service | ||
| import com.intellij.openapi.components.service | ||
| import com.intellij.openapi.fileEditor.FileEditorManager | ||
| import com.intellij.openapi.progress.ProgressManager | ||
| import com.intellij.openapi.progress.Task | ||
|
|
@@ -32,7 +33,7 @@ class PullRequest( | |
| var files: List<FileDetails> = mutableListOf() | ||
| var gates: QualitySettingsData? = null | ||
| private val refreshTimeout: TimeoutManager = TimeoutManager() | ||
| private val api = Api() | ||
| private val api = service<Api>() | ||
| private var repositoryManager: RepositoryManager? = null | ||
|
Comment on lines
35
to
37
|
||
|
|
||
| fun init( | ||
|
|
||
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.