Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
2d7cfee
ADFA-6228: Store a per-source package tree derived from indexed entries
itsaky-adfa Sep 23, 2026
2395620
ADFA-6228: Scope FilteredIndex package lookups to its active sources
itsaky-adfa Sep 23, 2026
8adfe39
ADFA-6228: Record JVM packages from top-level class files and bump th…
itsaky-adfa Sep 23, 2026
c235909
ADFA-6228: Add source-scoped top-level class queries to JvmSymbolIndex
itsaky-adfa Sep 23, 2026
b06de9a
ADFA-6228: Share a JarIndexingService base between the JVM indexing s…
itsaky-adfa Sep 23, 2026
213e79e
style: spotless reformat, no functional change
itsaky-adfa Sep 23, 2026
714ea28
ADFA-6228: Resolve a Java module's classes JAR per call without throwing
itsaky-adfa Sep 23, 2026
2540b7a
ADFA-6228: Characterise the compile classpath delta left out of the l…
itsaky-adfa Sep 23, 2026
f91e010
ADFA-6228: Index project modules' own output JARs as a third JVM scope
itsaky-adfa Sep 23, 2026
9eefeb2
ADFA-6228: Register the module-output index and refresh it on project…
itsaky-adfa Sep 23, 2026
79246e4
ADFA-6228: Expose indexing progress as a StateFlow on IndexingService…
itsaky-adfa Sep 23, 2026
39d3af2
ADFA-6228: Report every JAR indexing pass to the manager's progress t…
itsaky-adfa Sep 23, 2026
2ac3dc6
ADFA-6228: Profile the library indexing pass as the Index libraries p…
itsaky-adfa Sep 23, 2026
0e62f02
style: spotless reformat, no functional change
itsaky-adfa Sep 23, 2026
e7dceaf
ADFA-6228: Throw UnreadableJarException instead of swallowing a JAR o…
itsaky-adfa Sep 23, 2026
1e4985e
ADFA-6228: Report unreadable JARs from the indexing pass, not the cla…
itsaky-adfa Sep 23, 2026
1003e15
ADFA-6228: Arbitrate the editor status slot between library indexing …
itsaky-adfa Sep 23, 2026
ad3a784
ADFA-6228: Show library indexing progress in the editor status and pr…
itsaky-adfa Sep 23, 2026
f52a849
ADFA-6228: Extract the module-output test's project fixtures for reuse
itsaky-adfa Sep 23, 2026
2e4770e
ADFA-6228: Add module-scoped classpath class lookup over the JVM symb…
itsaky-adfa Sep 23, 2026
add26e4
ADFA-6228: Extract the trie differential test's JAR resolution and mu…
itsaky-adfa Sep 23, 2026
3145cf9
ADFA-6228: Pin the module classpath lookup against the classpath trie…
itsaky-adfa Sep 23, 2026
1a29454
style: spotless reformat, no functional change
itsaky-adfa Sep 23, 2026
c2a5178
ADFA-6228: Add a Java class-name lookup over source, index-backed cla…
itsaky-adfa Sep 23, 2026
b88fc92
ADFA-6228: Resolve Java qualified names from the class index instead …
itsaky-adfa Sep 23, 2026
cee8fde
ADFA-6228: Complete Java class names from the class index, prefix-onl…
itsaky-adfa Sep 23, 2026
569b927
style: spotless reformat, no functional change
itsaky-adfa Sep 23, 2026
97ca79a
ADFA-6228: Add a visibility-aware import-candidate lookup to the Java…
itsaky-adfa Sep 23, 2026
3c972f6
ADFA-6228: Make Java AddImportAction optimistic and index-backed
itsaky-adfa Sep 23, 2026
703f694
style: spotless reformat, no functional change
itsaky-adfa Sep 23, 2026
eba5f5a
ADFA-6228: Complete Java import paths from the class index instead of…
itsaky-adfa Sep 23, 2026
0426888
ADFA-6228: Delete the no-module import path completion
itsaky-adfa Sep 23, 2026
9417f76
ADFA-6228: Remove publicTopLevelTypes and the per-compiler classpath …
itsaky-adfa Sep 23, 2026
980f17e
style: spotless reformat, no functional change
itsaky-adfa Sep 23, 2026
c124f28
ADFA-6228: Stop stat'ing the file in BaseJavaCodeAction.prepare
itsaky-adfa Sep 23, 2026
41afefe
ADFA-6228: Filter AutoFixImportsAction candidates by visibility
itsaky-adfa Sep 23, 2026
fc2bbff
style: spotless reformat, no functional change
itsaky-adfa Sep 23, 2026
ad993d3
ADFA-6228: Add lsp:xml dependency on the JVM symbol index
itsaky-adfa Sep 23, 2026
74c3fbc
ADFA-6228: Read the layout tag completers' classpath children from th…
itsaky-adfa Sep 23, 2026
dff23a3
ADFA-6228: Skip the redundant classpath query in import path completion
itsaky-adfa Sep 23, 2026
f507198
ADFA-6228: Stat the file in findModuleForFile only when existence is …
itsaky-adfa Sep 23, 2026
50fd7b3
ADFA-6228: Make the Java LSP drop stale completion caches while index…
itsaky-adfa Sep 23, 2026
49fc5e1
ADFA-6228: Correct the module-output index KDoc's reader claim
itsaky-adfa Sep 23, 2026
fbbad19
ADFA-6228: Add test timeouts and restore ANDROID_JAR after lookup tests
itsaky-adfa Sep 23, 2026
4b49def
ADFA-6228: Drop JvmModuleOutputIndexingService's unused workspaceSupp…
itsaky-adfa Sep 23, 2026
1d980a4
ADFA-6228: Refresh the library index on initialization
itsaky-adfa Sep 23, 2026
1711d91
ADFA-6228: Remove the findQualifiedNames lookups left without callers
itsaky-adfa Sep 23, 2026
e2ce9a8
ADFA-6228: Create ProjectManagerImpl's indexing service manager under…
itsaky-adfa Sep 23, 2026
3ad8b69
ADFA-6228: Replace FilteredIndex's active sources in one assignment
itsaky-adfa Sep 25, 2026
5d8467f
ADFA-6228: Re-index a source in place instead of deleting its rows first
itsaky-adfa Sep 25, 2026
8cb4c58
ADFA-6228: Give each class source its own completion prefix limit
itsaky-adfa Sep 25, 2026
a6f19b8
ADFA-6228: Restore the status indexing replaced once it ends
itsaky-adfa Sep 25, 2026
66b5916
ADFA-6228: Hide Java add-import for a file in no module
itsaky-adfa Sep 25, 2026
4d24efc
ADFA-6228: Reset the Java completion cache on every finished indexing…
itsaky-adfa Sep 25, 2026
3f4ae74
ADFA-6228: Keep every classpath index's prefix matches in Java type l…
itsaky-adfa Oct 7, 2026
2e2e618
ADFA-6228: Key Kotlin extension callables by their receiver too
itsaky-adfa Oct 7, 2026
ae72c8e
ADFA-6228: Import an unimported type alias chosen from Kotlin completion
itsaky-adfa Oct 7, 2026
c0a49c3
ADFA-6228: Leave member callables out of the unimported-symbol queries
itsaky-adfa Oct 7, 2026
7091494
ADFA-6228: Look up Java auto-import candidates after releasing the co…
itsaky-adfa Oct 8, 2026
03264c8
ADFA-6228: Complete boot classpath imports in a Java file in no module
itsaky-adfa Oct 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.appdevforall.codeonthego.indexing.service.IndexingState
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode.MAIN
import org.slf4j.Logger
Expand Down Expand Up @@ -404,6 +405,7 @@ abstract class BaseEditorActivity :
@UiThread set(value) {
field = value
onUpdateProgressBarVisibility()
postIndexingStatusUpdate()
}

private var debuggerService: DebuggerService? = null
Expand Down Expand Up @@ -1608,17 +1610,47 @@ abstract class BaseEditorActivity :

private fun onUpdateProgressBarVisibility() {
log.debug(
"onBuildStatusChanged: isInitializing: ${editorViewModel.isInitializing}, isBuildInProgress: ${editorViewModel.isBuildInProgress}",
"onBuildStatusChanged: isInitializing: ${editorViewModel.isInitializing}, isBuildInProgress: ${editorViewModel.isBuildInProgress}, isIndexing: ${editorViewModel.isIndexing}",
)
// An internal build owns the same Gradle slot, so it shows the same progress bar. It does
// NOT relabel the Run button: the cancel affordance stays keyed off isBuildInProgress.
val visible =
val visible = isStatusOwnedElsewhere || editorViewModel.isIndexing
content.progressIndicator.visibility = if (visible) View.VISIBLE else View.GONE
invalidateOptionsMenu()
}

/*
* Whether a build, project initialization or debugger start owns the progress bar and status slot.
* An internal build owns the same Gradle slot as a user build, but it does NOT relabel the Run
* button: the cancel affordance stays keyed off isBuildInProgress.
*/
private val isStatusOwnedElsewhere: Boolean
get() =
editorViewModel.isBuildInProgress ||
editorViewModel.isInternalBuildInProgress ||
editorViewModel.isInitializing ||
isDebuggerStarting
content.progressIndicator.visibility = if (visible) View.VISIBLE else View.GONE
invalidateOptionsMenu()

private fun onIndexingStateChanged(state: IndexingState) {
val wasIndexing = editorViewModel.isIndexing
editorViewModel.onIndexingStateChanged(state)
if (editorViewModel.isIndexing != wasIndexing) {
onUpdateProgressBarVisibility()
}
onUpdateIndexingStatus()
}

private fun onUpdateIndexingStatus() {
editorViewModel.updateIndexingStatus(isStatusOwnedElsewhere) { done, total ->
getString(string.status_indexing_classes, done, total)
}
}

/*
* Deferred to the next main-loop message: the callbacks that clear a slot-owning flag often
* write their final status (e.g. "Build was cancelled") after clearing it, and the indexing
* text must replace that write rather than be overwritten by it.
*/
private fun postIndexingStatusUpdate() {
lifecycleScope.launch(Dispatchers.Main) { onUpdateIndexingStatus() }
}

private fun setupStateObservers() {
Expand Down Expand Up @@ -1656,17 +1688,31 @@ abstract class BaseEditorActivity :
}
}
}

launch {
ProjectManagerImpl
.getInstance()
.indexingServiceManager.state
.collect { state -> onIndexingStateChanged(state) }
}
}
}

editorViewModel._isBuildInProgress.observe(this) { inProgress ->
onUpdateProgressBarVisibility()
postIndexingStatusUpdate()
// The bottom sheet's collapsed header follows the status line's height; while the
// build narrates one line per task it only grows, or the peek jumps on every task.
content.bottomSheet.setBuildNarrating(inProgress == true)
}
editorViewModel._isInternalBuildInProgress.observe(this) { onUpdateProgressBarVisibility() }
editorViewModel._isInitializing.observe(this) { onUpdateProgressBarVisibility() }
editorViewModel._isInternalBuildInProgress.observe(this) {
onUpdateProgressBarVisibility()
postIndexingStatusUpdate()
}
editorViewModel._isInitializing.observe(this) {
onUpdateProgressBarVisibility()
postIndexingStatusUpdate()
}
editorViewModel._statusText.observe(this) {
content.bottomSheet.setStatus(
it.first,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.appdevforall.codeonthego.indexing.service.IndexingState
import java.io.File
import java.io.IOException
import java.util.Collections
Expand Down Expand Up @@ -250,6 +251,50 @@ class EditorViewModel : ViewModel() {
_statusText.value = (_statusText.value?.first ?: "") to value
}

/** The latest class indexing state the editor has observed. */
var indexingState: IndexingState = IndexingState.Idle
private set

/** Whether class indexing is in flight, derived from [indexingState]. */
val isIndexing: Boolean
get() = indexingState is IndexingState.Indexing

/** The indexing text last written to the status slot, or null if none is shown. */
private var shownIndexingStatus: CharSequence? = null

/** The message the indexing text replaced in the status slot, restored when indexing ends. */
private var replacedStatus: CharSequence? = null

/** Records [state], as reported by the project's indexing service manager. */
internal fun onIndexingStateChanged(state: IndexingState) {
indexingState = state
}

/**
* Updates the status slot for [indexingState], formatting its progress with [formatProgress].
*
* [isSlotOwnedElsewhere] is true while a build, project initialization or debugger start owns
* the slot; see [resolveIndexingStatus].
*/
fun updateIndexingStatus(
isSlotOwnedElsewhere: Boolean,
formatProgress: (done: Int, total: Int) -> CharSequence,
) {
val indexingStatus = (indexingState as? IndexingState.Indexing)?.let { formatProgress(it.done, it.total) }
val current = statusText
val next =
resolveIndexingStatus(isSlotOwnedElsewhere, indexingStatus, current, shownIndexingStatus, replacedStatus)
?: return
if (indexingStatus != null && shownIndexingStatus?.contentEquals(current) != true) {
replacedStatus = current
}
if (indexingStatus == null) {
replacedStatus = null
}
shownIndexingStatus = indexingStatus
_statusText.value = next to CENTER
Comment thread
itsaky-adfa marked this conversation as resolved.
}

var displayedFileIndex: Int
get() = _displayedFile.value!!
set(value) {
Expand Down Expand Up @@ -489,3 +534,27 @@ class EditorViewModel : ViewModel() {
return manager.projectDir.name
}
}

/**
* Decides what the status slot shows next for class indexing, or returns null to leave it alone.
*
* While [isSlotOwnedElsewhere] (a build, project initialization or debugger start is running) the
* slot is left to that operation. Otherwise [indexingStatus], the progress text or null when
* indexing is idle, takes it. When indexing ends the slot goes back to [replacedStatus], the message
* the indexing text replaced (a build result, say), or is cleared if there was none. It does so
* only if the slot still shows [shownIndexingStatus], the indexing text last written there, so a
* newer message survives.
*/
internal fun resolveIndexingStatus(
isSlotOwnedElsewhere: Boolean,
indexingStatus: CharSequence?,
currentStatus: CharSequence,
shownIndexingStatus: CharSequence?,
replacedStatus: CharSequence? = null,
): CharSequence? =
when {
isSlotOwnedElsewhere -> null
indexingStatus != null -> indexingStatus.takeUnless { it.contentEquals(currentStatus) }
shownIndexingStatus?.contentEquals(currentStatus) == true -> replacedStatus ?: ""
else -> null
}
Comment thread
itsaky-adfa marked this conversation as resolved.
Loading
Loading