Skip to content

ADFA-4059: inconsistent search scope in source modules and project structure provider#1361

Merged
itsaky-adfa merged 5 commits into
stagefrom
fix/ADFA-4059
Jun 5, 2026
Merged

ADFA-4059: inconsistent search scope in source modules and project structure provider#1361
itsaky-adfa merged 5 commits into
stagefrom
fix/ADFA-4059

Conversation

@itsaky-adfa
Copy link
Copy Markdown
Contributor

@itsaky-adfa itsaky-adfa commented Jun 2, 2026

See ADFA-4059 for more details.

…e provider

Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>

# Conflicts:
#	app/src/main/java/com/itsaky/androidide/app/IDEApplication.kt
@itsaky-adfa itsaky-adfa requested a review from a team June 2, 2026 18:15
@itsaky-adfa itsaky-adfa self-assigned this Jun 2, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bea28e48-2197-48d6-a9d0-aa0cc89d61d8

📥 Commits

Reviewing files that changed from the base of the PR and between 2d83c83 and 8f23ea4.

📒 Files selected for processing (1)
  • app/src/main/java/com/itsaky/androidide/app/IDEApplication.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/java/com/itsaky/androidide/app/IDEApplication.kt

📝 Walkthrough

Release Notes - ADFA-4059: Fix Inconsistent Search Scope in Source Modules and Project Structure Provider

Architecture & Infrastructure

  • Refactored Kotlin compilation environment initialization - Extracted shared setup logic into new AbstractCompilationEnvironment base class centralizing IntelliJ/Kotlin Analysis API bootstrapping (headless mode, disposable lifecycle management, service registration)
  • Redesigned service registration system - Replaced monolithic LspServiceRegistrar with new modular AnalysisApiServiceProvider, LspAnalysisApiServiceRegistrar, and AnalysisApiServiceProviders abstractions for cleaner service binding
  • Introduced abstract module hierarchy - Added AbstractSourceModule to centralize source file discovery and content scope computation logic across module implementations
  • Made compilation classes inheritable - Marked JvmSymbolIndex and key module methods (FilteredIndex source methods) as open to support subclassing

Symbol Indexing & Search Scope

  • Changed local declaration handling - SourceFileIndexer now skips indexing of local functions and local properties (only top-level declarations are indexed)
  • Improved prefix-matching logic - Enhanced InMemoryIndex.resolveMatchingKeys to distinguish between prefix-searchable and non-searchable fields with better fallback handling for empty prefixes
  • Refactored content scope computation - Modules now compute base search scopes via overridable computeBaseContentScope() method; AbstractSourceModule uses path-based scope checking to avoid stale VirtualFile instances
  • Updated module structure - KtSourceModule now extends AbstractSourceModule instead of AbstractKtModule for consistent source file handling

Testing Infrastructure

  • New comprehensive test fixtures - Added KtLspTestEnvironment, KtLspTestRule, KtLspTest base class, and TestKtSourceModule for Kotlin LSP integration testing
  • Added regression tests - Introduced ContentScopeStalenessTest and SourceFileIndexerTest covering stale snapshot scenarios and local declaration exclusion

Other Changes

  • Removed manual setupIdeaStandaloneExecution call and java.awt.headless=true from application startup
  • Refactored AnalysisPermissionOptions to constructor-based property definition
  • Simplified ProjectStructureProvider by removing SLF4J logging dependency
  • Updated Kotlin Android artifact reference (tag and SHA-256 checksum)
  • Changed language server registry access pattern in test framework
  • Fixed TemporaryFolder initialization in test rule (removed manual create() call)

⚠️ Risks & Best Practices Notes

  • Large-scale refactoring - Multiple simultaneous architectural changes to initialization and service registration increase regression risk; thorough integration testing required
  • Breaking behavior change in indexing - Excluding local declarations from the symbol index may impact IDE features relying on local symbol navigation
  • Incomplete test cleanup - KtLspTestRule has a commented-out env.close() with TODO noting test failures; incomplete resource cleanup could cause test leaks
  • Stale VirtualFile workaround - Path-based scope checking introduced to work around VirtualFile staleness; this is a workaround rather than addressing root cause
  • Removed headless configuration - Removal of java.awt.headless=true and setupIdeaStandaloneExecution requires verification for headless/non-UI environments

Walkthrough

Extracts a reusable AbstractCompilationEnvironment, replaces the monolithic service registrar with provider-based registrars, refactors source-module discovery and scopes, improves index behavior and overridability, skips local declarations during indexing, and adds JVM test fixtures and regression/unit tests.

Changes

Kotlin Compilation Environment Refactoring

Layer / File(s) Summary
Abstract compilation environment and initialization
lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/AbstractCompilationEnvironment.kt, lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/CompilationEnvironment.kt
AbstractCompilationEnvironment centralizes IntelliJ/Kotlin Analysis API setup, compiler configuration, and lifecycle; CompilationEnvironment now extends it, adds coroutine-scoped initialization, diagnostics publishing, and FIR invalidation publishing.
Service registration abstraction and providers
lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/registrar/AnalysisApiServiceProvider.kt, lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/registrar/AnalysisApiServiceProviders.kt, lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/registrar/LspAnalysisApiServiceRegistrar.kt
Adds AnalysisApiServiceProvider types and builder, a provider registry (AnalysisApiServiceProviders), and LspAnalysisApiServiceRegistrar that applies provider registrations to mock application/project component managers (replacing removed monolithic registrar).
Compiler configuration and invalidation
lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/KotlinLanguageServer.kt
Switches metadata index construction to KtFileMetadataIndex.sqliteBacked(...) and integrates FIR session invalidation publishing in file/module modification flows.

Module System and Source File Discovery

Layer / File(s) Summary
Abstract module base and scope computation
lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AbstractKtModule.kt, lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AbstractSourceModule.kt
Adds computeBaseContentScope() hook and AbstractSourceModule which implements source-file discovery (walk content roots, filter .kt/.java) and a path-based GlobalSearchScope to avoid stale-VFS issues.
KtSourceModule refactoring and declaration providers
lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/KtSourceModule.kt, lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/services/DeclarationsProvider.kt
KtSourceModule now inherits AbstractSourceModule (removing its own file-walk); DeclarationProvider now extends AbstractDeclarationProvider which centralizes project and defines ktFilesForPackage hook.

Index System Improvements

Layer / File(s) Summary
FilteredIndex overridability
lsp/indexing/src/main/kotlin/org/appdevforall/codeonthego/indexing/FilteredIndex.kt
Makes active-source management methods open for subclasses and refactors query/get/contains to consistently consult isActive(sourceId).
InMemoryIndex prefix-match enhancement
lsp/indexing/src/main/kotlin/org/appdevforall/codeonthego/indexing/InMemoryIndex.kt
resolveMatchingKeys now supports bucketed prefix-searchable fields (case-insensitive) and a case-sensitive fallback for non-prefix fields; empty prefix on bucketed fields returns bucket contents.
JvmSymbolIndex and KtFileMetadataIndex abstractions
lsp/jvm-symbol-index/src/main/kotlin/org/appdevforall/codeonthego/indexing/jvm/JvmSymbolIndex.kt, lsp/jvm-symbol-index/src/main/kotlin/org/appdevforall/codeonthego/indexing/jvm/KtFileMetadataIndex.kt
JvmSymbolIndex is now open; KtFileMetadataIndex depends on Index<KtFileMetadata> rather than a concrete SQLite type and exposes sqliteBacked factory.
Source file indexer local declaration skip
lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/index/SourceFileIndexer.kt
analyzeFunction and analyzeProperty early-return for local declarations (dcl.isLocal), preventing indexing of locals.

Test Infrastructure and Fixtures

Layer / File(s) Summary
Test base class and JUnit rule
lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTest.kt, lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTestRule.kt
Adds KtLspTest Robolectric-backed test base with helpers and KtLspTestRule to provision temp source roots and test environment lifecycle.
Test environment fixture and module implementation
lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTestEnvironment.kt, lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/TestKtSourceModule.kt
KtLspTestEnvironment extends the new abstract compilation environment to create SDK/stdlib/source/library modules, wire in-memory symbol indexes, and provide createSourceFile + analyze helpers; TestKtSourceModule supplies test module metadata.
Test cases and regression tests
lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/compiler/index/SourceFileIndexerTest.kt, lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTestEnvironmentTest.kt, lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/ContentScopeStalenessTest.kt
Adds tests verifying local-declaration skipping in the index, fixture correctness (source creation and cross-file resolution), and content-scope staleness regression coverage.

Supporting and Cleanup Changes

Layer / File(s) Summary
Application setup and service cleanup
app/src/main/java/com/itsaky/androidide/app/IDEApplication.kt, lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/services/AnalysisPermissionOptions.kt, lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/services/ProjectStructureProvider.kt
Removes the setupIdeaStandaloneExecution import/call and the java.awt.headless property set from application startup; refactors AnalysisPermissionOptions to constructor-based properties and removes SLF4J logger from ProjectStructureProvider.
Dependency and API updates
subprojects/kotlin-analysis-api/build.gradle.kts, testing/lsp/src/main/java/com/itsaky/androidide/lsp/api/LSPTest.kt, shared/src/main/java/com/itsaky/androidide/utils/Either.kt
Updates an external Kotlin-Android artifact tag and checksum, switches a test accessor to ILanguageServerRegistry.default, and includes a minor EOF brace edit.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • Daniel-ADFA
  • jatezzz
  • dara-abijo-adfa

Poem

🐰 I hopped through modules, scopes, and indexes bright,
Built a shared env to make the analyses light,
Providers register, tests spin up in a whirl,
Locals are skipped, and symbols unfurl,
A carrot-coded cheer from your little dev rabbit!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main objective: fixing inconsistent search scope in source modules and project structure provider, which aligns with the primary refactoring across multiple module and indexing files.
Description check ✅ Passed The description references the Jira issue ADFA-4059 with a link, which is directly related to the changeset's core objective of fixing inconsistent search scope issues.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ADFA-4059

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTestRule.kt (1)

30-33: 💤 Low value

The env.project.write { } block is currently a no-op.

With env.close() commented out, the write block does nothing and env is never disposed, leaving its resources held for the duration of the suite. This is acknowledged via the TODO, but worth resolving so the environment is torn down between tests.

Want me to open an issue to track teardown of env (investigating why env.close() fails under test), or draft a working disposal sequence?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTestRule.kt`
around lines 30 - 33, The env.project.write { } block is a no-op because
env.close() is commented out, so ensure the test environment is reliably torn
down by calling env.close() from the rule's teardown rather than leaving it
inside the write block: move the disposal into a proper tearDown/after method in
KtLspTestRule, call env.close() (or Disposer.dispose(env) if close() is
unstable) inside a try/catch to swallow/log any exceptions, and null out the env
reference after successful disposal so resources are released between tests;
reference env, env.close(), env.project.write { }, and the KtLspTestRule
teardown method when applying the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AbstractSourceModule.kt`:
- Around line 10-28: The file uses kotlin.io.path.walk which is marked
experimental; add an opt-in for ExperimentalPathApi at the top of the file
(file-level) so the compiler allows use of kotlin.io.path.walk (or alternatively
enable -Xopt-in=kotlin.io.path.ExperimentalPathApi for the module); update
AbstractSourceModule (where computeFiles calls walk) to have
`@OptIn`(kotlin.io.path.ExperimentalPathApi::class) applied file-wide to suppress
the experimental API error.

In
`@lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTestRule.kt`:
- Around line 28-35: The TemporaryFolder created as tempDir is manually created
(tempDir.create()) and not registered as a JUnit rule, so its cleanup never
runs; update the teardown in the finally block of KtLspTestRule to explicitly
delete the tempDir (call tempDir.delete()) before or after env.project.write/
env.close() to ensure the temp src folder and written sources are removed;
reference the tempDir TemporaryFolder instance and the env teardown block (the
finally that currently checks ::env.isInitialized and calls env.project.write)
and add the explicit cleanup call there so temporary files are removed even when
tests fail.

In `@subprojects/kotlin-analysis-api/build.gradle.kts`:
- Around line 12-31: Replace the local absolute-file dependency in the
dependencies { api(files(...)) } block with the original externalAssets {
jarDependency("kt-android") { ... } } wiring: restore the externalAssets block
that uses AssetSource.External(url = uri(...), sha256Checksum = "..."), re-add
the AssetSource import if removed, and remove the hardcoded api(files(...))
entry so the build fetches the shared kt-android JAR via the external asset
mechanism with integrity verification.

---

Nitpick comments:
In
`@lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTestRule.kt`:
- Around line 30-33: The env.project.write { } block is a no-op because
env.close() is commented out, so ensure the test environment is reliably torn
down by calling env.close() from the rule's teardown rather than leaving it
inside the write block: move the disposal into a proper tearDown/after method in
KtLspTestRule, call env.close() (or Disposer.dispose(env) if close() is
unstable) inside a try/catch to swallow/log any exceptions, and null out the env
reference after successful disposal so resources are released between tests;
reference env, env.close(), env.project.write { }, and the KtLspTestRule
teardown method when applying the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1fd0c255-3161-4eb6-b157-b71e6449a3ad

📥 Commits

Reviewing files that changed from the base of the PR and between 1793332 and b6f9a7b.

📒 Files selected for processing (29)
  • app/src/main/java/com/itsaky/androidide/app/IDEApplication.kt
  • lsp/indexing/src/main/kotlin/org/appdevforall/codeonthego/indexing/FilteredIndex.kt
  • lsp/indexing/src/main/kotlin/org/appdevforall/codeonthego/indexing/InMemoryIndex.kt
  • lsp/jvm-symbol-index/src/main/kotlin/org/appdevforall/codeonthego/indexing/jvm/JvmSymbolIndex.kt
  • lsp/jvm-symbol-index/src/main/kotlin/org/appdevforall/codeonthego/indexing/jvm/KtFileMetadataIndex.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/KotlinLanguageServer.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/AbstractCompilationEnvironment.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/CompilationEnvironment.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/index/SourceFileIndexer.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AbstractKtModule.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AbstractSourceModule.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/KtSourceModule.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/registrar/AnalysisApiServiceProvider.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/registrar/AnalysisApiServiceProviders.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/registrar/LspAnalysisApiServiceRegistrar.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/registrar/LspServiceRegistrar.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/services/AnalysisPermissionOptions.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/services/DeclarationsProvider.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/services/ProjectStructureProvider.kt
  • lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/compiler/index/SourceFileIndexerTest.kt
  • lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/ContentScopeStalenessTest.kt
  • lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTest.kt
  • lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTestEnvironment.kt
  • lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTestEnvironmentTest.kt
  • lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTestRule.kt
  • lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/TestKtSourceModule.kt
  • shared/src/main/java/com/itsaky/androidide/utils/Either.kt
  • subprojects/kotlin-analysis-api/build.gradle.kts
  • testing/lsp/src/main/java/com/itsaky/androidide/lsp/api/LSPTest.kt
💤 Files with no reviewable changes (2)
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/registrar/LspServiceRegistrar.kt
  • app/src/main/java/com/itsaky/androidide/app/IDEApplication.kt

Comment thread subprojects/kotlin-analysis-api/build.gradle.kts Outdated
@itsaky-adfa itsaky-adfa marked this pull request as draft June 2, 2026 18:28
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
@itsaky-adfa itsaky-adfa marked this pull request as ready for review June 2, 2026 18:48
@itsaky-adfa itsaky-adfa changed the title fix: inconsistent search scope in source modules and project structure provider ADFA-4059: inconsistent search scope in source modules and project structure provider Jun 5, 2026
@itsaky-adfa itsaky-adfa merged commit 3640116 into stage Jun 5, 2026
2 checks passed
@itsaky-adfa itsaky-adfa deleted the fix/ADFA-4059 branch June 5, 2026 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants