There's also SYNTHETIC_OFFSET, which is used for example for
declarations generated by interface delegation, for which
`sourceElement` threw exception. It didn't lead to any user-visible
error AFAIK, I've encountered this problem while working on 5f2ff06296.
It was already reported in the K2+PSI mode, but not LT because
BuilderFactoryForDuplicateClassNameDiagnostics relied on PSI, and did
not do anything if PSI was missing.
No tests were added because it fixes the already existing test
`compiler/testData/cli/jvm/fileClassClashMultipleFiles` after the
project is migrated to 2.0.
#KT-59586
Otherwise, navigation to unresolved reference is impossible ^ KTIJ-26441
In order to avoid duplicated diagnostic, wrapper is still used.
Symbol collector is updated to retrieve symbols from that wrapper.
Merge-request: KT-MR-11381
Merged-by: Anna Kozlova <Anna.Kozlova@jetbrains.com>
- `KtReadActionConfinementLifetimeToken` tracks its validity via the
project-wide out-of-block modification tracker. Out-of-block
invalidation of some LL FIR session will cause the lifetime tokens of
all analysis sessions to become invalid, including unrelated sessions,
because of this project-wide tracking.
- If `KtFirAnalysisSession`s are only invalidated when their underlying
LL FIR session is invalidated, the cache may expose analysis sessions
which contain invalid lifetime tokens after out-of-block modification.
Even though an analysis session will still be practically valid if its
underlying LL FIR session is valid, the lifetime token will *think*
that the PSI has changed and throw an "access to invalid token"
exception.
- Hence, we cannot currently invalidate `KtFirAnalysisSession`
granularly and project-wide OOBM tracking needs to be restored.
^KT-60272
- Due to problematic timing in `LLFirSession.invalidate` when the
function is called from a read action, it's better to remove the
function altogether.
- The function's only usage was session invalidation after exceptions
from resolve when FIR tree guards were turned off. Because FIR tree
guards are stable enough, the flag that turned them off can be
removed. This also allows removing `LLFirSession.invalidate`.
- The alternative to removing `LLFirSession.invalidate` would be to
rewrite session invalidation to be independent of write actions. That
would require additional locking in `LLFirSessionCache`, which we want
to avoid.
^KT-59297
- Module state modification events now have a modification kind, which
allows adding additional kinds of modification in the future (e.g.
separating module property and content root updates, if the workspace
model ever supports it).
- Splitting off modification kinds was also a good opportunity to
better document when module state modification occurs.
- Changed the documentation of modification events to be (1) less
reliant on the IDE implementation and (2) more detailed in the
intended effect of each event.
- Removed the notion of "stable" modules again and replaced it with
"libraries". Even though an SDK is technically not a library, the
term "library modules" should be more friendly to API consumers.
- Specifically for non-global module state modification, we can
guarantee that the event is published before the module is modified.
This allows subscribers to use the provided `KtModule` without needing
to fear that the module has already been disposed (in case of
removal).
- `KtFirAnalysisSession` does not need to depend on project out-of-block
and project root modification trackers anymore, as its underlying
use-site session determines validity. To ensure that use-site sessions
are invalidated in SLC equality tests, modification events also need
to be published.
- We do not need `AtomicBoolean` here, because setting `_isValid` to a
constant `false` suffices.
- Also replace the public setter of `isValid` with `markInvalid` to
prohibit setting `isValid` to `true` again.
- Out-of-block modification of stable modules is meaningless, because
stable modules should not be affected by out-of-block modification.
Hence, only global *source* out-of-block modification makes sense and
global out-of-block modification events can be removed.
- Any time an anchor module's session is invalidated, we need to make
sure that all its dependents are also invalidated. Because those
dependents may include libraries, invalidation after global source
modification needs to invalidate such libraries, even if other stable
module sessions should remain untouched.
- `LLFirSessionCache.sourceCache` can contain library and library
sources sessions. However, global source modification events should
not remove such sessions from the cache, because they belong to
"stable" modules.
- The commit introduces the term "stable module" as a combined term for
binary and library source modules. Library sources are not binaries,
but nevertheless they cannot cause nor be affected by out-of-block
modification.
- The term "source modules" as used by global "source" modification is
slightly imprecise, as it does *not* include library sources, but for
the sake of conciseness, I don't plan to change that.
- The lambda passed to `invokeLater` in `LLFirSession.invalidate` might
survive beyond project disposal (especially in tests), so me must not
capture a hard reference to the session that can leak its `project`.
- Until the IDE module dependents provider has been implemented for
script dependents (see KTIJ-25620), we must assume that any script
modification may lead to any other script session being out of date.
Hence, script modification now leads to the removal of all script
sessions.
- Because the IDE module dependents provider doesn't provide script
dependents for libraries yet, library modification must also lead to
global script session invalidation.
- We don't need to invalidate dependent sessions when the root session
isn't in the session cache, or if the session is already marked as
invalid, because any dependent sessions that might exist won't be
referencing entities from the root session at that point.
- Because `KtModule`s and thereby sessions may depend on each other
cyclically, we must not create a session during the creation of
another session. Otherwise, let's say session A and B depend on each
other. Then we get the following nested creation: session A -> session
B -> session A -> session B, and so on.
- Dependency symbol providers are in part taken from dependency
sessions. Hence, we have to create dependency symbol providers lazily.
- For the creation of dependency symbol providers we only need to access
the non-dependency symbol providers of a session dependency, so we
don't need to access the dependency's dependency symbol providers.
Hence, the lazy construction won't run into issues with cycles later
on.
^KT-57743 fixed
- Kotlin modification events are published before or after the
modification, depending on the underlying cause. For example, PSI tree
change events in the IDE can occur both before and after the change,
so module and global out-of-block modification events must not make
timing guarantees. Similarly, module state modification events
published by the IDE can both happen before and after a module change,
with most events happening before the change.
- This commit replaces session modification trackers with event-based
session invalidation. The removal of modification trackers should
improve overall performance, because session invalidation events
happen less frequently than sessions are accessed. Getting rid of
modification trackers also allows sessions to refer to other sessions
lazily, which is essential when cyclic dependencies occur.
- The new `LLFirSession` validity tracker has constant complexity and
will not cause the same kind of performance issues as dependency
modification trackers. It is a bridge to support modification trackers
in certain parts of the code (e.g. for `CachedValue`s), while being
backed by event-based invalidation.
- `LLFirSessionInvalidationService` is the bridge between modification
events and `LLFirSessionCache`. It finds out which modules should be
invalidated and instructs the session cache to remove the associated
sessions.
- Session invalidation must always happen in a write action to preserve
consistency between sessions. Otherwise, while a session A is already
removed from the cache, it might still be referenced by a dependent
session B which is in the process of being invalidated. Such a session
must never be returned from `getSession`.
^KT-57515 fixed
- The IDE implementation of `KotlinModuleDependentsProvider` cannot
easily find all dependents for a builtins or SDK module. Instead,
builtins and SDK changes can be handled via global module state
modification events, because most modules will depend on builtins and
SDK modules.