Commit Graph

56558 Commits

Author SHA1 Message Date
Denis Zharkov 579838cb4e Avoid recursive refinement in NewCapturedTypeConstructor
Potentially, it might contain infinite recursive supertypes
And for such cases, we have to perform lazy refinement (one level per request)
2019-07-30 12:41:41 +03:00
Denis Zharkov a2a1c7e50f Avoid recursive refinement with star projections
Otherwise StackOverflowError or recursion-detection in LockBasedStorageManager
may happen

It's fine to have non-refined type there because it only can affect
content of containing type member scope that should be refined after
being requested
2019-07-30 12:41:41 +03:00
Denis Zharkov d042eb2cfb Fix type refinement for qualified expressions
Previously, type for "c.a"-receiver in "c.a.platformFun()"
has not been refined because typechecking of "c.a" doesn't go
through common facade org.jetbrains.kotlin.types.expressions.ExpressionTypingServices#getTypeInfo
where the most of expressions are expected to be type checked.

(see org.jetbrains.kotlin.resolve.calls.CallExpressionResolver#getUnsafeSelectorTypeInfo)
2019-07-30 12:41:41 +03:00
Dmitry Savvinov 6695ddd1d5 Change 'hashCode' of 'TypeProjection'
according to bug when there was exception in
`hashCode` call when projection has some `SpecialType`
like `NO_EXPECTED_TYPE`
2019-07-30 12:41:41 +03:00
Dmitry Savvinov b103f42ca8 Add test on using correct builtins in MPP
Note that Native built-ins are not resolved correctly in this module
(CPointed and similar). This is not a bug, but rather a technical
limitation of the current testing infrastructure: we can't depend on
kotlin-native stdlib in "big-Kotlin" repo, and native stdlib is used as
the only one source of Native built-ins.
2019-07-30 12:41:41 +03:00
Dmitry Savvinov 1fe8e4ba15 Use CompositeResolve in HierarchicalExpectActual tests 2019-07-30 12:41:41 +03:00
Dmitry Savvinov aaf76a0e46 Enable TypeRefinement in COMPOSITE resolution mode 2019-07-30 12:41:41 +03:00
Dmitry Savvinov 2b4d70fcf0 [Resolve] Rewrite how built-ins are created
Under COMPOSITE mode we don't have a globally known way to create
built-ins, instead, we have to create them on per-module basis.

So, in this commit we:

1. Use builtInsProvider: (ModuleInfo) -> KotlinBuiltIns instead of
precomputed builtIns instance, in order to be able to calculate
builtIns on per-module basis

2. Introduce new entity, called BuiltInsCache, which, roughly
speaking, is a map of form ModuleInfo -> KotlinBuiltIns, to prevent
creation of multiple builtInsInstances
NB. Actually, it's of form BuiltInsCacheKey -> KotlinBuiltIns, because
we shouldn't create new builtIns for each module. Also, currently,
each platform has its own BuiltInsCacheKey implementation, because
parameters by which built-ins are created, are a bit different across
different platforms. Ideally, we should eliminate those differences
and they use one concrete implementation as a key.
2019-07-30 12:41:40 +03:00
Dmitry Savvinov 9f2a03947c [Resolve] Compute dependency on SDK properly
Under COMPOSITE resolution mode (see ResolutionModeComponent) we have
no fixed and globally known SDK, instead, for each module we have to
find SDK it it's transitive dependencies.

Currently, this is necessary in order to create proper JvmBuiltIns,
which need dependency on SDK to be present in immediate dependencies.
2019-07-30 12:41:40 +03:00
Dmitry Savvinov 02c07a4a6c [Resolve] Introduce an ability to get all moduleInfos without filtering by platform
Previously, each ProjectResolutionFacade was tied to the respective
platform, so there were no point in collection moduleInfos for all
possible platforms.

For composite resolution mode, we have to get all modules no matter
what their platform is (because all modules will be analyzed in one
facade), so this commit adds such an ability.
2019-07-30 12:41:40 +03:00
Dmitry Savvinov f9b8ab3a3a [Resolve] Introduce CompositeResolver
This commit introduces CompositeResolverForModuleFactory, which should
work under so-called "composite resolution mode", where sources of all
all modules are analyzed in one global facade.

This allows to:
- avoid re-analyzation of common sources
- avoid retaining memory for all platforms (which can be very bad as
soon as we'll start distinguishing various flavours of platforms,
especially "flavours" of common platform)
- support running platform-specific checks in common modules (e.g.,
report JVM_PLATFORM_DECLARATION_CLASH if common sources are going to have
it)
- support analysis of shared platform modules, like commonNative

This mode heavily depends on so-called "type refinement" support in the
compiler, which is introduced in other series of commits.

In this commit, CompositeResolver and related codepaths are left unused.
Also, this commit misses several important pieces of logic in
resolvers-setup code, which should be different for CompositeResolver
- computation of 'firstDependency'
- computation of built-ins
- computation of modules owned by facade

They will be covered in the following commits
2019-07-30 12:41:40 +03:00
Dmitry Savvinov adb0f5eaf9 [Resolve] Introduce CompositeAnalysisSettings
Because we want to support both COMPOSITE and SEPARATE resolution modes
at once, we have to leave 'globalFacadesPerPlatformAndSdk'-map, but in
COMPOSITE mode it should use less parameters for that map, and, in
particular, we shouldn't use Platform and SDK for equality.

This commit introduces separate instance which should be used in
COMPOSITE mode.

COMPOSITE mode itself will be introduced in the following commits.
2019-07-30 12:41:40 +03:00
Dmitry Savvinov 5e95890028 [Resolve] Introduce KotlinMultiplatformAnalysisModeComponent
Introduce a component which tells which resolution mode should be used.

COMPOSITE mode will analyze all sources for all platforms in one facade,
and will use proper support in the frontend instead of
CombinedModuleInfo.

SEPARATE mode is essentially a "legacy" mode, where each platform is
analyzed in separate facade (leading, in particular, to multiple
re-analyzation of common sources)

Facilities for support of COMPOSITE mode will be introduced in the
following commits.

resolution component
2019-07-30 12:41:40 +03:00
Dmitry Savvinov 90cf9daff3 [Resolve] Abstract creation of platform-specific package fragment providers 2019-07-30 12:41:40 +03:00
Dmitry Savvinov b48218e722 [Resolve] Make ResolversForModule less static
As consequence, remove IdePlatformKindTooling.resolverForModule, because
it became more than just field, and it duplicates similar API in
IdePlatformKindResolution anyways
2019-07-30 12:41:40 +03:00
Dmitry Savvinov 0f56d243cb [Resolve] Support test/production/dependsOn internal-visibility 2019-07-30 12:41:40 +03:00
Dmitry Savvinov c50eeb3edb Add few tests on internal visibility in MPP 2019-07-30 12:41:40 +03:00
Dmitry Savvinov 43ef0ffa50 [Testing] Support diagnostics filters in MultiModuleIdeResolveTest 2019-07-30 12:41:40 +03:00
Dmitry Savvinov 68c1a7cedd Use stable order for dependsOn and related diagnostics 2019-07-30 12:41:39 +03:00
Dmitry Savvinov 769ccde43b Closure over dependencies in multiPlatformSetup 2019-07-30 12:41:39 +03:00
Dmitry Savvinov 3c2e34ee08 [Misc] Fix bug in multiPlatformSetup
Due to a typo, dependency on fullJdk were added to the wrong module
2019-07-30 12:41:39 +03:00
Dmitry Savvinov 61ec5ed5dd [Misc] Introduce lazyClosure 2019-07-30 12:41:39 +03:00
Dmitry Savvinov 54cdd3bfef [Misc] Refactor Module.cached extension to accept lambda instead of FunctionalInterface 2019-07-30 12:41:39 +03:00
Dmitriy Novozhilov b477184a3c Fix creating of refined FlexibleType and RawType
There was an issue that `KotlinType.equals` called in `KotlinTypeFactory.flexibleType`
  and `RawType` constructor produced endless recursion of types that wasn't
  computed yet
2019-07-30 12:41:39 +03:00
Denis Zharkov 33a31fb688 [Tesdata fix] Fix test data for multiplatform highlighting test
Once refinement is introduced the behavior becomes correct
2019-07-30 12:41:39 +03:00
Denis Zharkov d744192e6f [Invariant fix] Fix false positive internal visibility diagnostic
Effectively, this commit allows for common module
to see internal content of all expect-modules

The problem is that when computing the member scope for A (see the test)
we're building a special member scope for CommonAbstract viewed from JVM
and it's effectively has a fake override of actual member from Jvm/ExpectBase.

OverridingUtil checks if it's visible in CommonAbstract and finds that it's not
thus creating a fake_invisible fake override

The latter results in A::foo override being marked as INVISIBLE_MEMBER_OVERRIDE

Probably, the fix might be smarter
(passing a requested module to OverridingUtil::createAndBindFakeOverride)
but allowing using internal member seems to be safe & simple
because it's reasonable to assume there's no cyclic dependencies
between expected/actual modules
2019-07-30 12:41:39 +03:00
Denis Zharkov d20516779a [Invariant Fix] Avoid using invalid descriptors in RemovePartsFromPropertyFix
org.jetbrains.kotlin.descriptors.InvalidModuleException: Accessing invalid module descriptor <production sources for module light_idea_test_case> is a module[ModuleDescriptorImpl@89f9a78]
	at org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl.assertValid(ModuleDescriptorImpl.kt:51)
	at org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl.getPackage(ModuleDescriptorImpl.kt:70)
	at org.jetbrains.kotlin.descriptors.FindClassInModuleKt.findClassifierAcrossModuleDependencies(findClassInModule.kt:23)
	at org.jetbrains.kotlin.types.KotlinTypeKt.refineDescriptor(KotlinType.kt:185)
	at org.jetbrains.kotlin.descriptors.impl.AbstractClassDescriptor$1$1.invoke(AbstractClassDescriptor.java:50)
	at org.jetbrains.kotlin.descriptors.impl.AbstractClassDescriptor$1$1.invoke(AbstractClassDescriptor.java:47)
	at org.jetbrains.kotlin.types.SimpleTypeImpl.refine(KotlinTypeFactory.kt:210)
	at org.jetbrains.kotlin.types.SimpleTypeImpl.refine(KotlinTypeFactory.kt:182)
	at org.jetbrains.kotlin.types.AbstractTypeConstructor$ModuleViewTypeConstructor.getSupertypes(AbstractTypeConstructor.kt:38)
	at org.jetbrains.kotlin.types.AbstractTypeConstructor$ModuleViewTypeConstructor.getSupertypes(AbstractTypeConstructor.kt:33)
	at org.jetbrains.kotlin.types.TypeUtils.getImmediateSupertypes(TypeUtils.java:230)
	at org.jetbrains.kotlin.types.TypeUtils.collectAllSupertypes(TypeUtils.java:255)
	at org.jetbrains.kotlin.types.TypeUtils.getAllSupertypes(TypeUtils.java:268)
	at org.jetbrains.kotlin.idea.util.TypeUtils.getResolvableApproximations(TypeUtils.kt:128)
	at org.jetbrains.kotlin.idea.util.TypeUtils.getResolvableApproximations$default(TypeUtils.kt:126)
	at org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention$Companion$createTypeExpressionForTemplate$1.invoke(SpecifyTypeExplicitlyIntention.kt:133)
	at org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention$Companion.createTypeExpressionForTemplate(SpecifyTypeExplicitlyIntention.kt:149)
	at org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention$Companion.addTypeAnnotationWithTemplate(SpecifyTypeExplicitlyIntention.kt:234)
	at org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention$Companion.addTypeAnnotationWithTemplate$default(SpecifyTypeExplicitlyIntention.kt:229)
	at org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention$Companion.addTypeAnnotation(SpecifyTypeExplicitlyIntention.kt:195)
	at org.jetbrains.kotlin.idea.quickfix.RemovePartsFromPropertyFix.invoke(RemovePartsFromPropertyFix.kt:82)
	at org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction.invoke(KotlinQuickFixAction.kt:37)
	at com.intellij.codeInsight.intention.impl.IntentionActionWithTextCaching$MyIntentionAction.invoke(IntentionActionWithTextCaching.java:179)
	at com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler.lambda$invokeIntention$4(ShowIntentionActionsHandler.java

See QF tests like QuickFixTestGenerated$RemoveRedundantInitializer.testSimple
2019-07-30 12:41:39 +03:00
Denis Zharkov 5f10252185 [Invariant fix] Avoid using obsolete desciptors as scope content in change signature
After type refinement was introduced we sometimes may request
some additional data from ModuleDescriptor

But if it's been invalidated after first part of refactoring's been applied
requesting content may fail (see ModuleDescriptorImpl::assertValid)

See the test:
org.jetbrains.kotlin.idea.refactoring.introduce.ExtractionTestGenerated.IntroduceLambdaParameter#testLambdaParamInPrimaryConstructor
2019-07-30 12:41:39 +03:00
Denis Zharkov 01f0589ddf [Invariant Fix] Use the same lock inside single GlobalFacade
Before refinement, order of accessing compiler's entities (supertypes,
descriptors, memberscopes) was always the following:

    sources -> libraries -> SDK (built-ins)

With refinement, it is sometimes possible to inverse this order, e.g.
access sources after libraries or SDK. This mainly happens in the following
scenario:

- we reference some library/SDK class, but do not acquire source-lock
  This might seem a bit weird, but actually it is quite easy to achieve
  as soon as we understand that analysis sources doesn't necessarily
  acquires respective lock, only forcing lazy computations does so.
  E.g., we can just traverse PSI tree and meet some refernce to "Any?" -
  this doesn't involves acquiring source-lock

- we start resolving it, which usually involves acquiring library/SDK-lock
  (e.g., in order to get it supertypes or memberScope)

- because we reference it from the source-module, we may like to refine
  it, in which case we will have to acquire source-lock on refinement
  cache

Obviously, that may lead to deadlocks, so, in this commit we disable
creating granular locks when we work with refinement.

Note that if refinement is disabled (which is the case for all non-MPP
projects), we still create separate locks.
2019-07-30 12:41:39 +03:00
Denis Zharkov fd4d8176dd [Misc Invariant Fix] Do not use KotlinType::toString in inspections
Because, there's no strict limitations on toString format there
and ModuleViewTypeConstructor#toString violates it
2019-07-30 12:41:38 +03:00
Denis Zharkov daa27016ca [Invariant Fix] Adjust DataFlowValue::Identifier for refinement
After refinement is introduced it becomes possible to have a different
descriptors instances for effectively the same descriptors

Also, it accidentally fixes KT-25432 because is caused by a different
version of descriptors created for NewCapturedType

^KT-25432 Fixed
2019-07-30 12:41:38 +03:00
Denis Zharkov 21cc93860b [Invariant Fix] Fix KotlinPsiUnifier after types refinement introduction
Refined types with non-trivial substitution may result in different
descriptors instances
See PsiUnifierTestGenerated$Equivalence$Expressions.testArrayAccess
2019-07-30 12:41:38 +03:00
Denis Zharkov c49791f8bb [Invariant Fix] Fix equality for NewCapturedTypeConstructor after refinement 2019-07-30 12:41:38 +03:00
Denis Zharkov 471134d31e [Invariant Fix] Fix callable equivalence definition in case of refined scopes
Before types refinement has been introduced it was reasonable to assume
that whenever we have two callables in the same declaration
they are actually different

But it become false once types refinement were introduced
and the same declarations may appear as different descriptors' instances
when viewing from different modules

The change does look very fragile because in many cases
source element is NO_SOURCE

At the same time, declaring actually different members
with the same signature is prohibited and may make sense only
in case of source-based members
2019-07-30 12:41:38 +03:00
Denis Zharkov 5c2c7e7776 [Invariant fix] Avoid re-resolving declared descriptors in lazy member scopes
It becomes necessary after scopes/types refinement
Without it being applied the code might fail with slice-rewrite errors

KT-32841
2019-07-30 12:41:38 +03:00
Dmitry Savvinov ab9ff786d7 [Invariant Fix] Use structural descriptor equivalence in JsNamesClashChecker
It's needed for situation when we have JS module with expect declaration,
so we refine member scope for that expect declaration and try to
compare to function descriptors (e.g. of `equals` function) from
different class descriptors (expect and actual) and report diagnostic
about name clash. So, since we can earn descriptors from type refinement,
they can be not identical but still equals, so with should use structural
equality to comparing them
2019-07-30 12:41:38 +03:00
Dmitriy Novozhilov 9add14a2a1 [API Usage] Add refinement to ConstraintInjector (NI) 2019-07-30 12:41:38 +03:00
Dmitry Savvinov 6c44b6b859 [API Usage] Refine type of lambda's receiver in NI
It's needed because of lambda's receiver is not an expression and
  we can not refine it in usual way in TypingVisitor
2019-07-30 12:41:38 +03:00
Dmitriy Novozhilov 696aea004d [API Usage] Add type refinement for callable references 2019-07-30 12:41:38 +03:00
Denis Zharkov 53334c038f [API Usage] Use refinement in NI 2019-07-30 12:41:37 +03:00
Denis Zharkov 2bf6bd3724 Do not consider descriptors equality as a reason not to refine type
Otherwise, it results in skipping refinement for JobNode when requested
from JVM module while it's necessary because CompletionHandlerBase's content
depends on the module
2019-07-30 12:41:37 +03:00
Denis Zharkov 9c27abde7f [API Usage] Support type refinement from expect class to type aliases
It's necessary when expect class is actualized via typealias
To support it properly, we need to return AbbriviatedType instead of
SimpleTypeImpl, thus scopeFactory is not enough anymore
2019-07-30 12:41:37 +03:00
Dmitry Savvinov 04717b57c9 [API Usage] Support refinement for Java classes' scope
Also, we should skip supertypes refinement for additional
    built-in members scope
2019-07-30 12:41:37 +03:00
Denis Zharkov b7e011a29b [API Usage] Use type refinements in overrides-related facilities 2019-07-30 12:41:37 +03:00
Denis Zharkov 694f521bfd [API Usage] Refine type for each separate element in ExpressionTypingVisitorDispatcher 2019-07-30 12:41:37 +03:00
Dmitriy Novozhilov a1b52b2f90 [API Usage] Inject Refiner into KotlinTypeChecker, use it for subtyping 2019-07-30 12:41:37 +03:00
Dmitry Savvinov 9047ddfc2f [API Usage] Refine supertypes when getting content of member scope 2019-07-30 12:41:37 +03:00
Dmitry Savvinov 1d61d75225 [Core API] Introduce KotlinType.refine
The most interesting part happens in SimpleType.refine, other types
either don't implement refinement at all (they return just 'this',
mainly it's some special types, like ErrorType and such) or implement
it trivially via recursion (those are "composite" types)

SimpleType.refine captures so-called refinement factory, which is essentially
an injected callback which tells how to reconstruct the type with new
(refined) memberScope.

We have to inject callback because we express quite different types with
SimpleTypeImpl, and some of them need different refinement logic.
Another possible implementation approach (more invasive one) would be
to extract those types in separate subtypes of KotlinType and implement
'refine' via overrides.

The most meaningful callbacks are injected from
'AbstractClassDescriptor.defaultType' and from 'KotlinTypeFactory'.
2019-07-30 12:41:37 +03:00
Dmitry Savvinov c12f5f6055 [Core API] Introduce TypeConstructor.refine
This commit introduces TypeConstructor.refine method.

It's implementation can be roughly split in three parts:
- trivial implementations which just return 'this': mostly, it used for
typeConstructors which can not be refined at all (e.g.
IntegerValueTypeConstructor and other special cases of constructors)

- delegating implementations which call 'refine' recursively for
component typeConstructors -- obviously, they are used in composite
typeConstructors (like IntersectionTypeConstructor)

- finally, the most interesting one is in 'AbstractTypeConstructor'
which returns lightweight wrapper called 'ModuleViewTypeConstructor'.
The idea here is to propagate refinement to supertypes without eagerly
computing them all.

VERY IMPORTANT CAVEAT of TypeConstructor.refine is that call to this
method CAN NOT add new supertypes, so returned supertypes are not
entirely "valid". See the KDoc for TypeConstructor.refine for details
2019-07-30 12:41:37 +03:00
Denis Zharkov c20d565d93 [Core API] Introduce API for getting scopes with refinement
- All refinement-related methods are incapsulated in
ModuleAwareClassDescriptor

- most of classes implement it trivially by retning unchanged scope

- LazyClassDescriptor and DeserializedClassDescriptor have non-trivial
implementations of the refinement-related methods

- General idea is to return new scope which captures refiner and will
later use it to get correct content of itself (currently, refiner is
unused, and will be used for that in later commits)

- In order to not repeat similar work, those new instances of scopes are
cached in ScopeHolderForClass, which is essentially a cache of form
KotlinTypeRefiner -> MemberScope
2019-07-30 12:41:37 +03:00