Commit Graph

40 Commits

Author SHA1 Message Date
Jaebaek Seo e80f044847 K2: Update reference shortener to handle import alias
The existing reference shortener does not use import alias when it
shortens a symbol. Instead, it adds a new import directive for the
symbol that is already imported. This commit updates reference shortener
to let it reuse the existing import alias rather than adding a new one:

 1. When shortening a symbol, check whether the symbol is already
    imported.
 2. If it is already imported by an import alias, keep the symbol
    reference expression and the import alias as a string together in
    `ShortenCommand`.

The actual PSI update (shortening) based on the ShortenCommand is done
by IntelliJ.

^KTIJ-27205
2023-11-09 14:34:38 +00:00
Roman Golyshev b0f15451fd KT-62676 [AA] Collect redundant this qualifiers in reference shortener
^KT-62676 Fixed
2023-11-01 09:45:40 +00:00
Roman Golyshev 44d48510b4 KTIJ-26057 [AA] Ignore implicit receivers scope when dealing with types in reference shortener
Implicit receivers generally do not affect the resolution of types.
However, they generate scopes which might contain undesirable
classifiers, which can confuse reference shortener.

Dropping all the implicit receivers when dealing with type references
allows completely avoid such undesirable scopes instead of filtering
them by `instanceof` checks.

Also, temporary move `hasTypeParameterFromParent` check higher to the
`findClassifierElementsToShorten`, because ATM we don't know how to
properly decide whether to shorten the fully-qualified inner types
with implicit parameters or not (see KTIJ-26072).

^KTIJ-26057 Fixed
2023-10-24 07:47:30 +00:00
Roman Golyshev d2fcd71d23 KTIJ-27139 [AA] Shorten qualified expressions only when the callee/type reference is in selection
If you want to shorten call like `foo.bar()` into `bar()`, then you
need your range to intersect with `bar` callee reference. Having only
`foo` in the range is not enough

Same goes for the type references - to shorten `foo.Bar` into `Bar`, you
need at least some intersection of your range with `Bar` reference

^KTIJ-27139 Fixed
^KTIJ-27015 Fixed
2023-10-16 20:05:01 +00:00
Roman Golyshev a78d631b16 KTIJ-27050 [Analysis API] Correctly handle type parameters in KtFirReferenceShortener
Make `FirShorteningContext` correctly return symbols for type
parameters, so they are not ignored when scopes are inspected

Add additional type of `PartialOrderOfScope` - `TypeParameter`, because
otherwise it would have been classified as `Unclassified`, and that
breaks scopes comparison

Add missing type parameters to the scope of class header in
`ContextCollector`, add testdata for that

There is a bug in the compiler with type parameters leaking to nested
classes headers (KT-61959). After it's fixed, the testData with
incorrect expected shortenings/scopes should be adjusted and fixed too

^KTIJ-27050 Fixed
2023-09-18 10:23:30 +00:00
Roman Golyshev 7b50506aea KT-61889 [AA] Migrate KtFirReferenceShortener to ContextCollector
This should make reference shortener considerably faster, since it won't
need to perform redundant extra resolve of the file.

`ContextCollector` more accurately collects the scopes for the scripts,
so some script tests are also fixed.

It should fix the following bugs:

^KTIJ-26714 Fixed
^KTIJ-26727 Fixed

This is also an important part of fixing the following bugs:
- KTIJ-26715
- KTIJ-26734

But those bugs also rely on KT-61890, because completion uses scopes
and snows incorrect elements from them
2023-09-13 16:43:20 +00:00
Roman Golyshev 1766c68e9c [FIR][AA] Rely more on isInBestCandidates flag KtFirReferenceShortener
After the KT-61568 has been fixed, `isInBestCandidates`
correctly works in more cases, and can be more
reliably used in `KtFirReferenceShortener`

^KTIJ-26808 Fixed
^KTIJ-26840 Fixed
2023-08-31 08:45:34 +00:00
Roman Golyshev c8ae22eb66 KTIJ-26785 [AA] Filter JavaClassMembersEnhancementScope when shortening types
The same way as `FirClassUseSiteMemberScope` is present
when there is an implicit receiver with a pure Kotlin type,
`JavaClassMembersEnhancementScope` is present when
the receiver's type comes from Java sources

^KTIJ-26785 Fixed
2023-08-28 15:21:40 +00:00
Dmitrii Gridin 5557ea690d [AA] add generated tests for scripts
^KT-61431
2023-08-28 15:02:24 +00:00
Roman Golyshev b760046f93 KTIJ-26713 [AA] Clean-up KtFirReferenceShortener
- revert some accidental changes in
`findSmallestElementOfTypeContainingSelection` function (see 48433bf9)
- simplify `dropFakeRootPrefixIfPresent` by using `tail`, add a new
test-case to check that it works
- simplify `findClassifierElementsToShorten` by not passing lambdas and
calling a common functions instead
2023-08-21 16:22:22 +00:00
Roman Golyshev 24a13348c4 KTIJ-26713 [AA] Handle FirFunctionTypeParameter in KtFirReferenceShortener
^KTIJ-26713 Fixed
2023-08-21 16:22:22 +00:00
Roman Golyshev 52d6ac5ed0 [AA] Fix processing of member invoke functions from objects in reference shortening and import optimization
Correctly handle `KtDotQualifedExpression`s with function calls as
selectors (like `foo.Bar()`). Without such handling, processing of
member invoke calls on objects was broken both
for reference shortener (causing KTIJ-26695)
and import optimizer (causing KTIJ-23407)

Also, to fix KTIJ-23407, do not ignore qualifiers with
`ImplicitInvokeCall` fake source

^KTIJ-26695 Fixed
^KTIJ-23407 Fixed
2023-08-18 07:32:05 +00:00
Roman Golyshev 48433bf9fd [Analysis API] Unwrap anonymous function expressions in reference shortener
Anonymous functions are additionally wrapped into an expression

^KTIJ-26629 Fixed
^KTIJ-26597 Fixed
2023-08-14 18:03:12 +00:00
Roman Golyshev b52d3c114f KTIJ-26627 [AA] Correctly handle object receivers of property accesses
Also remove redundant code from `canBePossibleToDropReceiver`

^KTIJ-26627 Fixed
2023-08-13 22:20:19 +02:00
Roman Golyshev 93124ee98c KT-60957 [Analysis API] Properly handle source PSI for implicit invoke calls in KtFirReferenceShortener
For implicit invoke operator calls, there are two instances of
`FirResolvedNamedReference`. One of them references `invoke` function
and cannot be used to analyze the property access, and the second one
has `source == null`. Luckily, the parent of the second reference is
`FirPropertyAccessExpression`, which has the correct source

^KT-60957 Fixed
2023-08-10 16:51:31 +00:00
Roman Golyshev 71a4f36faf KTIJ-26576 [Analysis API] Add where clause to classHeaderParts in FirTowerDataContextAllElementsCollector
In `where` clause there are type constraints, and there are no
supertypes scopes at those positions

^KTIJ-26576 Fixed
2023-08-09 06:49:48 +00:00
Dmitrii Gridin 734a3e5716 [LL FIR] do not create lazy bodies during on-air resolve in scripts
We assume that on-air resolve already has normal bodies,
so depending on this fact, we can omit some redundant work

^KT-61026 Fixed
2023-08-08 15:40:48 +00:00
Roman Golyshev d46be70933 KT-60940 [Analysis API] Properly handle vararg types in KtFirReferenceShortener
^KT-60940 Fixed
^KTIJ-26518 Fixed
2023-08-07 08:35:49 +00:00
Roman Golyshev ab8726cff1 KT-60954 [Analysis API] Unwrap variable assignments in KtFirReferenceShortener
To get to the proper qualified expression, we need to unwrap the outer
`FirVariableAssignment` if we deal with the property access inside of
assignment expressions

^KT-60954 Fixed
2023-08-04 15:26:34 +00:00
Dmitrii Gridin 1a3b0fa9d5 [LL FIR] provide script scopes to declarations
All transformations inside a script should be
under the script context for proper resolution

^KT-60728
2023-08-02 16:50:45 +00:00
Andrei Klunnyi 0323b0fb19 KT-59801 [FIR] scripting: tests for reference shortening 2023-07-13 15:21:39 +02:00
aleksandrina-streltsova 39bdd67df6 [AA] Shortener: change test data
Remove ON_AIR_CONTEXT_CARET_TAG where it's not necessary
2023-07-04 16:34:53 +00:00
aleksandrina-streltsova 9766270afa [AA] Shorten kdocs that became available because of newly added imports 2023-07-04 16:34:52 +00:00
aleksandrina-streltsova 88f2bf85eb [AA] Test shortener for the whole file with different options 2023-07-04 16:34:51 +00:00
aleksandrina-streltsova 67c3849538 [Analysis API] Shortener: enable shortening in KDoc
^KTIJ-21103
2023-07-04 16:34:51 +00:00
Roman Golyshev c5ded1ba48 KTIJ-26103 [Analysis API] Ignore implicit dispatch receivers in Reference Shortener
Calls to extension functions imported from objects have implicit
dispatch receivers, but those receivers are not present in the code
and should not be analyzed by the shortener

^KTIJ-26103 Fixed
2023-07-03 20:05:09 +00:00
Roman Golyshev ab149e1053 KTIJ-26024 [Analysis API] Add more tests for nested cases of reference shortening in class header
Account for `FirNestedClassifierScopeWithSubstitution` in the reference
shortener
2023-07-03 16:21:42 +00:00
Roman Golyshev 88450c69b3 KTIJ-26024 [Analysis API] Provide correct context for class header from FirTowerDataContextAllElementsCollector
To correctly provide the context for class header resolution, we save
the additional copy of the context right before `withRegularClass`
wrapper call in `LLFirBodyLazyResolver`. Otherwise we would have to
clear the existing context by hand, which is too cumbersome
(if at all possible)

^KTIJ-26024 Fixed
^KTIJ-24832 Fixed
2023-07-03 16:21:42 +00:00
Roman Golyshev 96697b5a77 KTIJ-26024 [Analysis API] Rearrange testData for reference shortener
Move testData for nested classes' scopes to a separate directory
2023-07-03 16:21:42 +00:00
aleksandrina-streltsova 57cbab7d8e [AA] Shortener: allow import if requested import kind has high priority 2023-07-03 15:08:05 +00:00
aleksandrina-streltsova a96e2f37e7 [Analysis API] Shortener: don't add import if it affects usages
^KTIJ-24096 Fixed
2023-07-03 15:08:04 +00:00
aleksandrina-streltsova da5f33d762 [Analysis API] Do not shorten qualifiers outside the selection range
^KTIJ-25116 Fixed
2023-07-03 15:08:04 +00:00
aleksandrina-streltsova ed7a3299f0 [Analysis API] Shorten qualifier of unresolved reference
^KTIJ-25115
2023-07-03 15:08:03 +00:00
Ilya Kirillov ba3a3915c7 [Analysis API] tests: use tagged caret to find declaration to analyze in the air against
We cannot use a KtFile as analysis context.

^KT-55527
2023-05-04 15:26:50 +00:00
Ilya Kirillov e9f75b1350 [LL FIR] add test which checks reference shortening for the whole file
^KT-57966
2023-05-04 15:26:50 +00:00
Roman Golyshev f662908440 KTIJ-25232 [FIR IDE] Do not shorten properties with non-trivial receiver
If property call receiver is something real (like another property or a
function call), then it should not be shortened because the semantics
might change

^KTIJ-25232 Fixed
2023-04-13 15:48:08 +00:00
Jaebaek Seo 820d027676 [K2] Avoid shortening duplicated PSI elements
The existing K2 reference shortener collects all the PSI elements to
shorten. As a result, it possibly shortens duplicated PSI elements. For
example,
```
// FILE: main.kt
package a.b.c

fun test(n: Int) {
    return if (<expr>x.y.z.Outer.Inner.VALUE0 > x.y.z.Outer.Inner.VALUE1</expr>) 1
    else n
}
// FILE: values.kt
package x.y.z

class Outer {
    object Inner {
        val VALUE0 = 13
        val VALUE1 = 17
    }
}
```
for the above code, the existing K2 reference shortener tried to shorten
- x.y.z.Outer.Inner -> Inner
- x.y.z.Outer.Inner.VALUE0 -> VALUE0
- x.y.z.Outer.Inner -> Inner
- x.y.z.Outer.Inner.VALUE1 -> VALUE1

`x.y.z.Outer.Inner` is included in the list to shorten twice.
When it actually shortens the PSI elements, it shortens only
- x.y.z.Outer.Inner.VALUE0 -> VALUE0
- x.y.z.Outer.Inner.VALUE1 -> VALUE1

but it imports all of
- x.y.z.Outer.Inner
- x.y.z.Outer.Inner.VALUE0
- x.y.z.Outer.Inner.VALUE1

As a result, it has unnecessary additional import directives.
This commit fixes the issue by avoiding duplicated shortening for a
single PSI element.
2023-04-10 11:00:11 +00:00
aleksandrina-streltsova d89d774411 [AA] Consider context receivers in FirTowerDataElement.getAvailableScope 2023-03-20 22:04:48 +00:00
Ilya Kirillov 3ec032212c [Analysis API] Ignore FirClassUseSiteMemberScope scopes in KtFirReferenceShortener
Those scopes always contain all nested classifiers,
while only some of them are available without
explicit import. There are other, more reliable
scopes (like FirNestedClassifierScopeWithSubstitution)
which are stricter about which classifiers
they recognise as valid

^KTIJ-24684 Fixed
^KTIJ-24662 Fixed
2023-03-01 22:38:11 +00:00
Jaebaek Seo a09d0aa1cf Handle SHORTEN_IF_ALEADY_IMPORTED case of KtFirReferenceShortener
For the following example, when we run the reference shortener, it
drops `a.b.c` qualifier, because it matches "FOURTH".
```
package a.b.c

fun <T, E, D> foo(a: T, b: E, c: D) = a.hashCode() + b.hashCode() + c.hashCode() // FIRST
fun <E> E.foo() = hashCode() // SECOND

object Receiver {
    fun <T, E, D> foo(a: T, b: E, c: D) = a.hashCode() + b.hashCode() + c.hashCode() // THIRD
    fun foo(a: Int, b: Boolean, c: String) = a.hashCode() + b.hashCode() + c.hashCode() // FOURTH
    fun test(): Int {
        fun foo(a: Int, b: Boolean, c: Int) = a + b.hashCode() + c // FIFTH
        return <expr>a.b.c.foo(1, false, "bar")</expr>
    }
}
```

As shown in the above example, when SHORTEN_IF_ALEADY_IMPORTED option is
given from a user, the reference shortener has to check whether it can
drop the qualifier without changing the referenced symbol and if it is
possible to do that without adding a new import directive, it deletes
the qualifier.

It needs two steps:
 1. Collect all candidate symbols matching the signature e.g., function
    arguments / type arguments
 2. Determine whether the referenced symbol has the highest reference
    priority when we drops the qualifier depending on scopes

This commit uses `AllCandidatesResolver(shorteningContext.analysisSession.useSiteSession).
getAllCandidates( .. fake FIR call/property-access ..)` for step1.
For step2, we use a heuristic based on scopes of candidates. If a
candidate symbol is under the same scope with the target expression, it
has a `FirLocalScope` which has the high priority. So when we have a
candidate under a `FirLocalScope` and the actual referenced symbol is
different from the candidate, we must avoid dropping its qualifier
because the shortening will change its semantics i.e., reference.

The order of scopes depending on their scope types is:
 1. FirLocalScope
 2. FirClassUseSiteMemberScope / FirNestedClassifierScope
 3. FirExplicitSimpleImportingScope
 4. FirPackageMemberScope
 5. others

Note that for "others" the above rule can be wrong. Please update it if
you find other scopes that have a priority higher than the specified
scopes.

One of non-trivial parts is the priority among multiple
FirClassUseSiteMemberScope and FirNestedClassifierScope. They are
basically scopes for class declarations. We decide their priorities
based on the distance of class declaration from the target expression.

Note that we take a strict approach to reject all false positive. For
example, when we are not sure, we don't shorten it to avoid changing its
semantics.

TODO: One corner case is handling receivers. We have to update
```
private fun shortenIfAlreadyImported(
    firQualifiedAccess: FirQualifiedAccess,
    calledSymbol: FirCallableSymbol<*>,
    expressionInScope: KtExpression,
): Boolean
```

The current implementation cannot handle the following example:
```
package foo
class Foo {
    fun test() {
        // It references FIRST. Removing `foo` lets it reference SECOND.
        <caret>foo.myRun {
            42
        }
    }
}
inline fun <R> myRun(block: () -> R): R = block()         // FIRST
inline fun <T, R> T.myRun(block: T.() -> R): R = block()  // SECOND
```

Tests related to TODO:
 - analysis/analysis-api/testData/components/referenceShortener/referenceShortener/receiver2.kt
 - analysis/analysis-api/testData/components/referenceShortener/referenceShortener/receiver3.kt
2023-02-08 18:39:12 +00:00